在一对一关联中,JPA没有规定谁为关系的维护方,OneToOne的mapped属性值指定了由另外一方实体的某个属性来维护一对一关联。以Person和IDCard为例。
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)
- @JoinColumn(name="idcard_id")
- public IDCard getIdcard() {
- return idcard;
- }
-
- }
- @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;
- }
-
- @OneToOne(mappedBy="idcard", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.REFRESH},
- optional=false, fetch=FetchType.EAGER)
- public Person getPerson() {
- return person;
- }
-
- }
1. 测试保存
- public void save() {
- EntityManagerFactory factory = Persistence.createEntityManagerFactory("refrigerator");
- EntityManager em = factory.createEntityManager();
- Person person = new Person("Johnson");
- IDCard idcard = new IDCard("330818198602260444");
-
- person.setIdcard(idcard);
- em.getTransaction().begin();
- 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
|