@Entity public class Customer implements Serializable { @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name="passport_fk") public Passport getPassport() { ... } @Entity public class Passport implements Serializable { @OneToOne(mappedBy = "passport") public Customer getOwner() { ... }
在双向关联中, 有且仅有一端是作为主体(owner)端存在的:主体端负责维护联接列(即外键FK). 对于不需要维护这种关系的从表则通过mappedBy属性进行声明. mappedBy的值指向主体的关联属性. 在上面这个例子中,mappedBy的值为 passport. 最后,不必也不能再在被关联端(owned side)定义联接列了,因为已经在主体端进行了声明.如果在主体没有声明@JoinColumu,系统自动进行处理: 在主表(owner table)中将创建联接列, 列名为:主体的关联属性名+下划线+被关联端的主键列名. 在上面这个例子中是passport_id, 因为Customer中关联属性名为passport, passport的主键是id.
注意:
只要有双向关联关系,必设mppedBy
ManyToOne关系中默认的fetch是 FetchType.EAGER
OneToMany关系中默认的fetch是 FetchType.LAZY
数据库中的一个树结构,对象的表现形式.
@Entity public class TreeObject { private int id; private String name; private TreeObject parent; private List<TreeObject> children = new ArrayList<TreeObject>(); @Id @GeneratedValue public int getId() { return id; } @ManyToOne @JoinColumn(name="parent_id") public TreeObject getParent() { return parent; } @OneToMany(cascade=CascadeType.ALL,mappedBy="parent") @OrderBy("name ASC") public List<TreeObject> getChildren() { return children; } ....................
生成的表结构:
create table TreeObject ( id integer not null auto_increment, name varchar(255), parent_id integer, primary key (id) ) alter table TreeObject add index FK95A4309DA50A61ED (parent_id), add constraint FK95A4309DA50A61ED foreign key (parent_id) references TreeObject (id)
ManyToOne和OneToMany双向关系上,在OneToMany端设置mappedBy,表示主体端是Many端,关系的主导是One端的getChildren集合中的TreeObject的parent对象负责维持关系,也就是说我们用下面的方法就可以保存这些关系.
@Test public void testSaveTreeObject() { TreeObject o = new TreeObject(); o.setName("总公司"); TreeObject o1 = new TreeObject(); o1.setName("分公司1"); TreeObject o2 = new TreeObject(); o2.setName("分公司2"); o1.setParent(o); o2.setParent(o); Session s = sessionFactory.openSession(); s.beginTransaction(); s.save(o); s.save(o1); s.save(o2); s.getTransaction().commit(); s.close(); }
这段代码和上面的效果是一样的,因为@OneToMany(cascade=CascadeType.ALL,mappedBy="parent"),
CascadeType.ALL保存parent对象时,children也跟着保存了.
@Test public void testSaveTreeObject() { TreeObject parent = new TreeObject(); parent.setName("总公司"); TreeObject child1 = new TreeObject(); child1.setName("分公司1"); TreeObject child2 = new TreeObject(); child2.setName("分公司2"); child1.setParent(parent); child2.setParent(parent); parent.getChildren().add(child1); parent.getChildren().add(child2); Session s = sessionFactory.openSession(); s.beginTransaction(); s.save(parent); s.getTransaction().commit(); s.close(); }
数据库表中生成三条记录:
id name parent_id
1 总公司 null
2 分公司1 1
3 分公司2 1