이전에 작성한 DataClient
에서 수행했던 기술적인 코드를 OrderRepository
라는 클래스 안으로 넣어서 쉽게 오브젝트를 만들면 나머지 모든 과정을 거쳐서 DB에 저장하는 기능을 만들어보자
OrderRespository
라는 빈을 정의해서 사용하려면 어디에 만들어야 할까?
OrderRespository
를 생성OrderRespository
클래스 안에는 새로운 주문을 DB에 저장하는 메서드를 생성 → save(Order oder)
save 메서드 내에는 DataConfig에 있던 새로운 주문을 DB에 저장하는 작업들을 이동시킴
public void save(Order order) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(order);
em.getTransaction().commit();
em.close();
}
EntityManager를 생성하기 위해 필요로하는 EntityManagerFactory가 필요함
스프링의 빈으로 만들어 지는 것이기 때문에 EntityManagerFactory 빈을 가지고와서 주입시켜줘야 됨(DI)
private final EntityManagerFactory emf;
public OrderRepository(EntityManagerFactory emf) {
this.emf = emf;
}
OrderRepository 빈 등록
@Bean
public OrderRepository orderRepository() {
return new OrderRepository(entityManagerFactory());
}
주의사항
FactoryBean이라고 끝나는 빈(LocalContainerEntityManagerFactoryBean
)은
entityManagerFactory
메서드를 호출해서 리턴되는 그 타입이 EntityManagerFactory
그 자체는 아님
@Bean
public OrderRepository orderRepository() {
return new OrderRepository(entityManagerFactory());
}
그래서
return new OrderRepository(entityManagerFactory());
처럼 호출해서 작성하게 되면 타입이 일치하지 않는다고 나옴
이 경우 스프링 컨테이너 내에서 EntityManagerFactory
타입을 추출해서 빈으로 등록하는 작업이 진행될 것인데 OrderRespository
라는 메서드를 호출할 때 파라미터로 전달해달라고 선언을 해두면 됨
oderRepository
메서드의 파라미터로 EntityManagerFactory emf
전달OrderRepository
생성자에 emf
전달@Bean
public OrderRepository orderRepository(EntityManagerFactory emf) {
return new OrderRepository();
}
⇒ 빈 메서드에 의해서 만들어지는 EntityManagerFactory
오브젝트를 가지고 올 수 있게 됨
주의사항 적용 최종
@Bean
public OrderRepository orderRepository(EntityManagerFactory emf) {
return new OrderRepository(emf);
}
public class DataClient {
public static void main(String[] args) {
BeanFactory benFactory = new AnnotationConfigApplicationContext(DataConfig.class);
OrderRepository repository = benFactory.getBean(OrderRepository.class);
Order order = new Order("100", BigDecimal.TEN);
repository.save(order);
System.out.println(order);
}
}
중간 작업 단계에서 에러 발생하는 경우(DB 연결 안됨 등) persist
메서드를 빠져나갈 것
RuntimeException
이므로 throws 선언은 하지 않아도 되지만
현재 transaction을 rollback처리하는 코드가 없음rollback처리 추가
public void save(Order order) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
try {
em.persist(order);
transaction.commit();
}
catch (RuntimeException e) {
if(transaction.isActive()) transaction.rollback();
throw e;
}
finally {
if(em.isOpen()) em.close();
}
}