Person类:
@Entity @Table(name="pillow") public class Person { private Integer id; private String name; private IDCard idcard; public Person() { } public Person(String name) { this.name = name; } @Id @GeneratedValue public Integer getId() { return id; } @Column(length=20, nullable=false) public String getName() { return name; } @OneToOne(cascade={CascadeType.ALL},optional=false) // optional specified to false means the corresponding column couldn't be nullable @JoinColumn(name="idcard_id") // Indicate the column name of the foreign key public IDCard getIdcard() { return idcard; } // Setters are omitted }
@Entity public class IDCard { private Integer id; private String cardno; private Person person; public IDCard() { } public IDCard(String cardno) { this.cardno = cardno; } @Id @GeneratedValue public Integer getId() { return id; } @Column(length=18, nullable=false) public String getCardno() { return cardno; } // mappedBy specifies the property of the corresponding class that maintains the relationship. Also indicates this entity is the maintained edge. @OneToOne(mappedBy="idcard", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.REFRESH}, optional=false, fetch=FetchType.EAGER) // Maintained edge public Person getPerson() { return person; } // Setters are omitted }
1. 测试保存
public void save() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("refrigerator"); EntityManager em = factory.createEntityManager(); Person person = new Person("Johnson"); IDCard idcard = new IDCard("330818198602260444"); // idcard.setPerson(person); person.setIdcard(idcard); em.getTransaction().begin(); // It's mandatory to open transaction to insert, update or delete data. em.persist(person); em.getTransaction().commit(); em.close(); factory.close(); }
当IDCard的person属性的optional为true时,上面的idcard.setPerson(person)可以省略,因为Person既设置了级联属性cascade={CascadeType.ALL},在保存Person实体的时候也会保存IDcard,又是关系的维护方,在它们之间建立关联。如果为false,在先保存idcard时候,由于not null约束,程序报错。
2. 测试更新:
EntityManagerFactory factory = Persistence.createEntityManagerFactory("refrigerator"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); IDCard idcard = em.find(IDCard.class, 1); idcard.setCardno("330624198802060168"); // em.merge(idcard); em.getTransaction().commit(); em.close(); factory.close();
em.merge(idcard)可以省略,因为idcard已经是托管态了,对它的修改在commit的时候都会提交到数据库。如果idcard是游离态则需要该语句。
3. 测试查询:
public void queryFromMaintained() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("refrigerator"); EntityManager em = factory.createEntityManager(); IDCard idcard = em.find(IDCard.class, 1); em.close(); factory.close(); System.out.println(idcard.getCardno()); System.out.println(idcard.getPerson().getName()); }
因为IDCard实体的person属性设置了fetch=FetchType.EAGER,jpa会使用一个SELECT连表查询出Person和IDCard。
如果fetch设置为FetchType.LAZY,jpa会使用两个SELECT语句(第一个查询出IDCard,第二个连表查询),不会产生EntityManager关闭导致的问题。
4. 测试删除:
public void deleteFromMaintained() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("refrigerator"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); IDCard idcard = em.find(IDCard.class, 1); em.remove(idcard); em.getTransaction().commit(); em.close(); factory.close(); }
当IDCard的person属性的optional为true时,能删除成功;为false时删除会报错:org.hibernate.PropertyValueException: not-null property references a null or transient value: com.john.bean.Person.idcard