JPA 一对一关联

在一对一关联中,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) // 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
}


[color=violet][size=small]1. 测试保存[/size][/color]

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约束,程序报错。


[color=violet][size=small]2. 测试更新:[/size][/color]

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是游离态则需要该语句。


[color=violet][size=small]3. 测试查询:[/size][/color]

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关闭导致的问题。


[color=violet][size=small]4. 测试删除:[/size][/color]

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值