@OneToMany 注解用来定义具有一对多的多值关联。例如:汽车和轮胎,一辆汽车可以拥有多个轮胎,但是一个轮胎只能属于某辆车。
如果集合使用泛型来定义元素类型,则不需要指定关联的目标实体类型;否则必须指定目标实体类。例如:
@OneToMany private List<CarTyre> CarTyre;
如果关系是双向的,则必须使用 mappedBy 元素来指定作为关系所有者的实体的关系字段或属性。
@OneToMany 注释可以在包含在实体类中的嵌入类中使用,以指定与实体集合的关系。如果关系是双向的,则必须使用 mappedBy 元素来指定关系的所有者实体的关系字段或属性。当集合是 java.util.Map 时,cascade 元素和 orphanRemoval 元素应用于映射值。
实例1: 使用泛型的一对多关联
// 在 Customer 中: @OneToMany(cascade=ALL, mappedBy="customer") public Set<Order> getOrders() { return orders; } // 在 Order 类中: @ManyToOne @JoinColumn(name="CUST_ID", nullable=false) public Customer getCustomer() { return customer; }
实例2: 不使用泛型的一对多关联
// 在 Customer 中: @OneToMany(targetEntity=com.acme.Order.class, cascade=ALL, mappedBy="customer") public Set getOrders() { return orders; } // 在 Order 类中: @ManyToOne @JoinColumn(name="CUST_ID", nullable=false) public Customer getCustomer() { return customer; }
实例3: 使用外键映射的单向一对多关联
// 在 Customer 中: @OneToMany(orphanRemoval=true) @JoinColumn(name="CUST_ID") // join 列在 Order 表中 public Set<Order> getOrders() { return orders; }
定义一方(One)和多方(Many)对象的级联关系,当对一方(One)对象进行了某个操作后,怎样影响到多方(Many)对象的操作。级联可取值如下:
(1)不定义,则对关系表不会产生任何影响
(2)CascadeType.PERSIST 级联新建
(3)CascadeType.REMOVE 级联删除
(4)CascadeType.REFRESH 级联刷新
(5)CascadeType.MERGE 级联更新
(6)CascadeType.ALL 表示同时选择 CascadeType.PERSIST、CascadeType.REMOVE、CascadeType.REFRESH 和 CascadeType.MERGE
定义关联属性何时进行加载,可选择项包括:FetchType.EAGER 和 FetchType.LAZY。如下:
FetchType.EAGER:表示关系类在主类加载的时候同时加载
FetchType.LAZY:表示关系类在被访问时才加载,默认值是 FetchType.LAZY。
拥有关联关系的字段,如果关系是单向的就不需要;如果是双向关系表,那么拥有关系的这一方有建立、解除和更新与另一方关系的能力;而另一方没有这种能力,只能被动管理;这个属性被定义在关系的被拥有方。支持双向 @OneToOne,双向 @OneToMany,双向 @ManyToMany。
指定在删除一方(One)数据的同时是否删除掉多方(Many)的数据。默认为 false,不删除多方(Many)数据;仅仅将一方(One)和连接表的数据进行删除。例如:一个主记录包含三条副记录
@OneToMany(cascade={ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, orphanRemoval = false) private Collection<UserOneToManyExt> userOneToManyExt;
客户端代码
EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // 插入数据 String uuid = UUID.randomUUID().toString(); List<UserOneToManyExt> userExts = new ArrayList<UserOneToManyExt>(); userExts.add(new UserOneToManyExt(uuid + "@qq.com", "http://www.hxstrive1.com")); userExts.add(new UserOneToManyExt(uuid + "@163.com", "http://www.hxstrive2.com")); userExts.add(new UserOneToManyExt(uuid + "@outlook.com", "http://www.hxstrive3.com")); UserOneToMany user = new UserOneToMany(); user.setName("张三-" + uuid); user.setAge(28); user.setUserOneToManyExt(userExts); em.persist(user); // 查询数据 String qlString = "select t from UserOneToMany t"; Query query = em.createQuery(qlString); List<UserOneToMany> userList = (List<UserOneToMany>) query.getResultList(); for (UserOneToMany item : userList) { // 删除数据 em.remove(item); } em.getTransaction().commit();
执行 SQL 脚本如下:
SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?] UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?] SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?] UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?] INSERT INTO UserOneToMany (id, age, name) VALUES (?, ?, ?) [params=?, ?, ?] INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?] INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?] INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?] INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?] INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?] INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?] SELECT t0.id, t0.age, t0.name FROM UserOneToMany t0 DELETE FROM UserOneToMany_UserOneToManyExt WHERE USERONETOMANY_ID = ? [params=?] DELETE FROM UserOneToMany WHERE id = ? [params=?]
如果 orphanRemoval = true,删除数据执行的 SQL 如下:
SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?] UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?] SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?] UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?] INSERT INTO UserOneToMany (id, age, name) VALUES (?, ?, ?) [params=?, ?, ?] INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?] INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?] INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?] INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?] INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?] INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?] SELECT t0.id, t0.age, t0.name FROM UserOneToMany t0 DELETE FROM UserOneToMany_UserOneToManyExt WHERE USERONETOMANY_ID = ? [params=?] DELETE FROM UserOneToMany WHERE id = ? [params=?] DELETE FROM UserOneToManyExt WHERE id = ? [params=?] DELETE FROM UserOneToManyExt WHERE id = ? [params=?] DELETE FROM UserOneToManyExt WHERE id = ? [params=?]
关联目标的实体类。一般不用指定,JPA 厂商会自动发现。例如:
@OneToMany(cascade=ALL, mappedBy="customer") public Set<Order> getOrders() { return orders; }
上面实例中,targetEntity 默认就是 Order.class;如果没有使用泛型,则需要手动指定,如下:
@OneToMany(cascade=ALL, targetEntity=Order.class) public Set getOrders() { return orders; }