스프링 일기 13 - JPA(4) Main에서 사용해보기
스프링 부트를 이용해서 main 함수에서 JPA를 간단하게 테스트를 해볼 수 없을까? 고민이 생겼습니다.
이전에 시도를 해봤지만, STS의 오류였는지 무엇 때문이었는지 모르겠지만 build가 먹통이 되는 버그가 생겨서 일단 보류했는데요.
에러가 나지도 않고 그냥 Build가 되지 않았던거라 프로젝트를 새로 만들어서 해보니 잘 되었기에, 본격적으로 main에서 사용해보면서 연습을 하려고 합니다.
1. EntityManagerFactory 만들기
스프링에서 persistenceUnit을 만들어서 Factory에 넣어줘 EntityManager를 만들고 번거롭게 작업을 해야한다는 글을 적은 적이 있는데요,
스프링 부트에서는 Repository가 아닌 main함수에서 EntityManagerFactory를 어떻게 생성해야할까요?
package com.example.demo;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceUnit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class JpaStudyApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(JpaStudyApplication.class, args);
EntityManagerFactory emf = context.getBean(EntityManagerFactory.class);
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
}
}
SpringApplication은 run메서드를 실행할 때, return값으로 context값을 반환합니다.
해당 컨텍스트에는 EntityManagerFactory를 Bean으로 관리하고 있으므로 Factory에 unit을 넣을 필요 없이, 그냥 가져와서 사용해주면 됩니다.
persistence-unit은 datasource에 관련된 값들을 가지고 있지만, 우리는 application.property에서 관리해주고 있으니 알아서 잘 찾아옵니다.
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: dbuser
password: dbpass
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
open-in-view: true
show-sql: true
hibernate:
ddl-auto: create
application.property 대신 application.yml을 사용하도록 하겠습니다. 이렇게 작성하면 EntityManager를 간단하게 만들 수 있습니다.
EntityTransaction을 만들어서 transaction을 begin해주면 이제 main함수에서도 jpa를 이용하여 데이터를 CRUD할 수 있습니다.
간단하게 연관관계 매핑을 시켜보도록 하겠습니다.
(하... 빌드 에러 때문에 이렇게 간단하게 테스트를 해볼 수 있던걸 굳이 Service랑 Repository 만들어서 지지고 볶고 한게 참... ㅠㅠ)
간단한 OneToOne 맵핑을 시켜보도록 하겠습니다.
package com.example.demo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name = "member")
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@OneToOne(mappedBy = "member")
@JoinColumn(name="LOCKER_ID")
private Locker locker;
public Member() {
super();
}
public Member(Long id, String username, Locker locker) {
super();
this.id = id;
this.username = username;
this.locker = locker;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Locker getLocker() {
return locker;
}
public void setLocker(Locker locker) {
this.locker = locker;
}
}
(롬복의 필요성....) 롬복이 없으니까 쓸데없이 코드가 길어지고 있습니다. 얼른 Lombok을 설치해야겠습니다
package com.example.demo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
@Entity
public class Locker {
@Id @GeneratedValue
@Column(name="LOCKER_ID")
private Long id;
public Member getMember() {
return member;
}
@OneToOne
@JoinColumn(name="MEMBER_ID")
private Member member;
public Locker() {
super();
}
public void setMember(Member member) {
this.member = member;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}
테이블과 객체지향의 패러다임을 일치시키기 위해 Member객체와 Locker 객체에 각각의 id값을 외래키로 가지는 것이 아닌 객체 자체를 집어넣어주었습니다.
@OneToOne을 이용하여 서로의 객체를 조인해주었는데, mappedBy를 이용해서 Member에는 Locker의 member와 연관관계를 맺어주었습니다.
이제 Locker가 만들어지고 해당 Locker에 Member객체를 set해주면 Member에는 자동으로 Locker객체가 들어갈 것입니다.
package com.example.demo;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceUnit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class JpaStudyApplication {
@PersistenceUnit
private EntityManagerFactory emf;
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(JpaStudyApplication.class, args);
EntityManagerFactory emf = context.getBean(EntityManagerFactory.class);
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member member = new Member();
member.setUsername("duljji2");
Locker locker = new Locker();
locker.setName("dulljji's locker");
locker.setMember(member);
em.persist(locker);
tx.commit();
}
}
바로 테스트를 해보겠습니다.
locker에 member를 넣었고, member에는 locker를 넣어주지 않았습니다.
하지만 DB를 확인해보면?
매칭이 잘 되는 것을 확인할 수 있습니다.
이제 main함수에서 JPA를 마음껏 사용해보면서 공부하면 될 것 같습니다.