 |
|
JPA를 사용한 이클립스와 데이터 접근 코드
이제 자바 퍼시스턴스 API 덕에 자바 언어로 데이터베이스를 다루는 일이 얼마나 쉬워졌는지와 애플리케이션의 도메인 모델을 만들기 시작함으로써 이클립스를 위한 Java EE가 이를 어떻게 지원하는지에 대해 설명하겠다.
JPA를 사용하여 도메인 모델 만들기
초창기 자바 개발자라면 데이터베이스를 작업하는 것이 얼마나 힘든 일인지 알 것이다. 보통 엄청난 JDBC 코드를 만들고 직접 긴 SQL 문자열을 작성하거나 엔티티 EJB와 많은 인터페이스를 만들고 배치 서술자를 작성해야 했다. 하지만 EJB V3.0과 JPA 덕에 그런 힘든 날은 갔다. EJB는 사용하기 쉬울 뿐 아니라 이를 사용하는 데 무거운 애플리케이션이 필요 없다.
이클립스의 Java EE는 JPA를 훌륭하게 지원한다. JPA 퍼스펙티브까지 있다. 이로 바꾸려면 Window > Open Perspective > Other를 선택하고 JPA
Development를 선택한다.
그림 32. 오픈 JPA 개발 퍼스펙티브
도메인 모델을 만드려면 간단한 자바 클래스만 만들면 된다. org.developerworks.baseball.Player라 부를 Players 테이블을 위한 클래스를 만드는 것으로 시작하자. 코드는 Listing 5와 같다.
Listing 5. Player 클래스
package org.developerworks.baseball;
public class Player {
private int id;
private String firstName;
private String lastName;
}
|
이 클래스를 위해 게터(getters)와 세터(Setters)가 필요할 것이다. 이클립스는 이를 쉽게 해결한다. Source > Generate
Getters and Setters를 선택하면 된다.
그림 33. 코드 생성하기
그러면 게터와 세터 생성(Generate Getters and Setters) 대화상자가 나타날 것이다. Select All을 클릭하고 OK를 클릭한다.
그림 34. 게터와 세터 생성하기
결과 코드는 Listing 6에서 볼 수 있다.
Listing 6. 게터, 세터가 있는 Player 클래스
package org.developerworks.baseball;
public class Player {
private int id;
private String firstName;
private String lastName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
|
클래스와 데이터베이스 테이블을 결합하려면 JPA 구조(JPA Structure) 창에서 Player 클래스를 클릭한다.
그림 35. JPA 구조
JPA Details에서 Map As > Entity를 선택한다.
그림 36. JPA 세부 사항
Table 섹션에서 스키마를 선택한다. Name 드롭다운에서 Players 테이블을 선택할 수 있을 것이다.
그림 37. 테이블 지정하기
이렇게 하면 코드가 변경된다.
그림 38. Player 코드 생성하기
Package Explorer에서 persistence.xml 파일을 선택하고 마우스 오른쪽 단추를 클릭한 후 JPA Tools > Synchronize Classes를 선택한다.
그림 39. 데이터베이스 동기화하기
이제 이클립스는 데이터베이스에 대해 코드의 유효성을 입증할 것이다. 이 때 코드는 유효하지 않다고 표기된다.
그림 40. 무효 Player 클래스
무슨 일이 벌어지고 있는 것인가? 그저 문제(Problems) 창을 보기 바란다.
그림 41. Problems 창
첫 번째 문제는 클래스에 일차 키가 지정되지 않았다는 것이다. 이를 고치려면 JPA 구조 창에서 Id 속성을 클릭하고 JPA Details 창에서 Map As > Id를 선택한다.
그림 42. ID 속성을 위한 JPA 세부 사항
또한 ID 행을 자동증대 행으로 만들었으므로 일차 키가 Identity 키 생성 전략을 사용한다고 지정해야 함을 기억하자. 또 다른 JPA 동기화를 수행한다면 문제 하나가 고쳐졌음을 볼 수 있다.
다른 문제는 JPA가 firstName과 lastName 필드를 Players 테이블의 행과 맞추지 못한다는 데 있다. 이는 자바 필드와 테이블 행에 같은 이름을 넣지 않았기 때문에 발생한 문제다. JPA Structure 창에서 firstName 필드를 선택하자. JPA Details의 드롭다운 목록에서 적절한 행을 고르자.
그림 43. firstName을 First_Name에 매핑
lastName 필드도 똑같이 하자. JPA 동기화를 한 번 더 수행하면 모든 문제가 고쳐진다. Player 클래스 코드는 업데이트되고 Listing 7과 같다.
Listing 7. 완성된 Player 클래스
package org.developerworks.baseball;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Column;
@Entity
@Table(schema="baseball", name = "Players")
public class Player {
@Id
@GeneratedValue(strategy=IDENTITY)
private int id;
@Column(name="First_Name")
private String firstName;
@Column(name="Last_Name")
private String lastName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
|
이제 똑같은 과정으로 Game 클래스를 만들고 이를 Games 테이블과 맞춘다. Game 클래스 코드는 Listing 8과 같다.
Listing 8. Game 클래스
package org.developerworks.baseball;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Column;
@Entity
@Table(schema="baseball", name = "Games")
public class Game {
@Id
@GeneratedValue(strategy=IDENTITY)
private int id;
@ManyToOne(optional=false)
@JoinColumn(name="Player_Id", nullable=false, updatable=false)
private Player player;
@Column(name="H")
private int hits;
@Column(name="2B")
private int doubles;
@Column(name="3B")
private int triples;
@Column(name="HR")
private int homeRuns;
@Column(name="BB")
private int walks;
@Column(name="R")
private int runs;
@Column(name="RBI")
private int rbis;
@Column(name="AB")
private int atBats;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Player getPlayer() {
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
public int getHits() {
return hits;
}
public void setHits(int hits) {
this.hits = hits;
}
public int getDoubles() {
return doubles;
}
public void setDoubles(int doubles) {
this.doubles = doubles;
}
public int getTriples() {
return triples;
}
public void setTriples(int triples) {
this.triples = triples;
}
public int getHomeRuns() {
return homeRuns;
}
public void setHomeRuns(int homeRuns) {
this.homeRuns = homeRuns;
}
public int getWalks() {
return walks;
}
public void setWalks(int walks) {
this.walks = walks;
}
public int getRuns() {
return runs;
}
public void setRuns(int runs) {
this.runs = runs;
}
public int getRbis() {
return rbis;
}
public void setRbis(int rbis) {
this.rbis = rbis;
}
public int getAtBats() {
return atBats;
}
public void setAtBats(int atBats) {
this.atBats = atBats;
}
}
|
클래스가 모두 매핑이 됐다. 마지막으로 persistence.xml을 편집할 일만 남았다. 이것이 자바 퍼시스턴스 API를 위한 메타데이터 클래스의 핵심이고 연결 정보를 포함하고 있다.
Listing 9. persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="baseball">
<class>org.developerworks.baseball.Game</class>
<class>org.developerworks.baseball.Player</class>
<properties>
<property name=\
"openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/baseball"/>
<property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
<property name="openjpa.ConnectionUserName" value="root"/>
<property name="openjpa.ConnectionPassword" value="password"/>
<property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO"/>
</properties>
</persistence-unit>
</persistence>
|
이클립스가 이미 이 파일에 클래스를 넣었다. 그러므로 데이터베이스에 맞는 연결 정보만 넣으면 된다. 지금까지 이클립스를 사용하여 데이터 접근을 위한 자바 퍼시스턴스 API를 설정했다. 이제 이 데이터를 위한 UI를 만들 준비가 됐다.
|