EJB 3.0(Public Draft)入門記 Java Persistence API Chapter3 その10
前回に引き続き、エンティティリスナとコールバックメソッドがお題です。
今回は実際にエンティティリスナを使って、コールバックメソッドがいつ呼び出されるか確認してみます。
エンティティEmployeeのエンティティリスナです。
public class EmployeeEntityListener { @PrePersist public void prePersist(Employee Employee) { System.out.println("@PrePersist: " + Employee.getName()); } @PostPersist public void postPersist(Employee Employee) { System.out.println("@PostPersist: " + Employee.getName()); } @PreRemove public void preRemove(Employee Employee) { System.out.println("@PreRemove: " + Employee.getName()); } @PostRemove public void postRemove(Employee Employee) { System.out.println("@PostRemove: " + Employee.getName()); } @PreUpdate public void preUpdate(Employee Employee) { System.out.println("@PreUpdate: " + Employee.getName()); } @PostUpdate public void postUpdate(Employee Employee) { System.out.println("@PostUpdate: " + Employee.getName()); } @PostLoad public void postLoad(Employee Employee) { System.out.println("@PostLoad: " + Employee.getName()); } }
エンティティEmployeeです。EntityListenerアノテーションつかってます。
@Entity(access=AccessType.FIELD) @EntityListener(EmployeeEntityListener.class) public class Employee { @Id(generate=GeneratorType.AUTO) private int id; private String name; // getter, setter省略 }
ステートレスセッションBeanです。persist、update、removeを別トランザクションでそれぞれ実行したり、同一トランザクションで一度に実行したりしてみました。mergeも試してみました。
@Stateless public class ClientBean implements Client { @PersistenceContext private EntityManager em; public Employee persist() { Employee employee = new Employee(); employee.setName("ゴン"); em.persist(employee); return employee; } public void update() { Query query = em.createQuery("select e from Employee e where e.name = 'ゴン'"); Employee employee = (Employee)query.getSingleResult(); employee.setName("うさはな"); } public void remove() { Query query = em.createQuery("select e from Employee e where e.name = 'うさはな'"); Employee employee = (Employee)query.getSingleResult(); em.remove(employee); } public void persistUpdateRemove() { persist(); update(); remove(); } public void merge(Employee employee) { em.merge(employee); } public static void main(String[] args) throws Exception { EJB3StandaloneBootstrap.boot(null); EJB3StandaloneBootstrap.deployXmlResource("ejb3-deployment.xml"); InitialContext ctx = new InitialContext(); Client client = (Client) ctx.lookup(Client.class.getName()); System.out.println("## PERSIST"); client.persist(); System.out.println("\n## UPDATE"); client.update(); System.out.println("\n## REMOVE"); client.remove(); System.out.println("\n## PERSIST AND REMOVE"); client.persistUpdateRemove(); System.out.println("\n## MERGE"); Employee employee = client.persist(); employee.setName("たくや"); client.merge(employee); EJB3StandaloneBootstrap.shutdown(); } }
実行結果。
## PERSIST @PrePersist: ゴン Hibernate: insert into Employee (name, id) values (?, null) Hibernate: call identity() @PostPersist: ゴン ## UPDATE Hibernate: select employee0_.id as id0_, employee0_.name as name0_ from Employee employee0_ where employee0_.name='ゴン' @PostLoad: ゴン @PreUpdate: うさはな Hibernate: update Employee set name=? where id=? @PostUpdate: うさはな ## REMOVE Hibernate: select employee0_.id as id0_, employee0_.name as name0_ from Employee employee0_ where employee0_.name='うさはな' @PostLoad: うさはな @PreRemove: うさはな Hibernate: delete from Employee where id=? @PostRemove: うさはな ## PERSIST AND REMOVE @PrePersist: ゴン Hibernate: insert into Employee (name, id) values (?, null) Hibernate: call identity() @PostPersist: ゴン Hibernate: select employee0_.id as id0_, employee0_.name as name0_ from Employee employee0_ where employee0_.name='ゴン' @PreUpdate: うさはな Hibernate: update Employee set name=? where id=? @PostUpdate: うさはな Hibernate: select employee0_.id as id0_, employee0_.name as name0_ from Employee employee0_ where employee0_.name='うさはな' @PreRemove: うさはな Hibernate: delete from Employee where id=? @PostRemove: うさはな ## MERGE @PrePersist: ゴン Hibernate: insert into Employee (name, id) values (?, null) Hibernate: call identity() @PostPersist: ゴン Hibernate: select employee0_.id as id0_0_, employee0_.name as name0_0_ from Employee employee0_ where employee0_.id=? @PostLoad: ゴン @PreUpdate: たくや Hibernate: update Employee set name=? where id=? @PostUpdate: たくや
同一トランザクションでpersist、update、removeしたときはPostLoadコールバックメソッドが呼ばれていないです、selectのクエリは実行されていますけど。すでに永続コンテキスト内にエンティティがあってエンティティの値とデータベース内の値に変更がないからLoadする必要なしということでしょうか。
これは予想通りでしたがmergeしたときはLoadされてUpdateされるんですね。
あと、コールバックメソッドの中で別のセッションBeanを呼んでその中でEntityManagerを使うということを試してみたのですが、やっぱり怒られました。