GVKun编程网logo

什么是双向 JPA OneToMany/ManyToOne 关联中的“关联的反面”?(双向关联是什么意思)

33

如果您想了解什么是双向JPAOneToMany/ManyToOne关联中的“关联的反面”?的相关知识,那么本文是一篇不可错过的文章,我们将对双向关联是什么意思进行全面详尽的解释,并且为您提供关于@Ma

如果您想了解什么是双向 JPA OneToMany/ManyToOne 关联中的“关联的反面”?的相关知识,那么本文是一篇不可错过的文章,我们将对双向关联是什么意思进行全面详尽的解释,并且为您提供关于@ ManyToMany / @ OneToMany mappingby属性用于双向关联、@ManyToOne JPA 关联的 CascadeType.ALL 是什么意思、@ManyToOne JPA关联和级联…不确定删除对象会发生什么、@OneToMany、@ManyToOne以及@ManyToMany讲解的有价值的信息。

本文目录一览:

什么是双向 JPA OneToMany/ManyToOne 关联中的“关联的反面”?(双向关联是什么意思)

什么是双向 JPA OneToMany/ManyToOne 关联中的“关联的反面”?(双向关联是什么意思)

@OneToManyJPA
注释参考的示例部分:

示例 1-59 @OneToMany - 带有泛型的客户类

@Entitypublic class Customer implements Serializable {    ...    @OneToMany(cascade=ALL, mappedBy="customer")    public Set<Order> getOrders() {         return orders;     }    ...}

示例 1-60 @ManyToOne - 带有泛型的订单类

@Entitypublic class Order implements Serializable {    ...    @ManyToOne    @JoinColumn(name="CUST_ID", nullable=false)    public Customer getCustomer() {         return customer;     }    ...}

在我看来,该Customer实体是该协会的所有者。但是,在mappedBy同一文档中对属性的解释中,写道:

如果关系是双向的,则将关联的反向(非拥有)侧的 mappedBy 元素设置为拥有该关系的字段或属性的名称,如示例 1-60 所示。

但是,如果我没记错的话,在示例中,mappedBy实际上是在关联的拥有方指定的,而不是在非拥有方。

所以我的问题基本上是:

  1. 在双向(一对多/多对一)关联中,哪个实体是所有者?我们如何将 One 指定为所有者?我们如何将多方指定为所有者?

  2. “关联的反面”是什么意思?我们如何将一侧指定为反面?我们如何将多面指定为反面?

答案1

小编典典

要理解这一点,你必须退后一步。在 OO 中,客户拥有订单(订单是客户对象中的列表)。没有客户就不可能有订单。因此,客户似乎是订单的所有者。

但在 SQL 世界中,一项实际上包含指向另一项的指针。由于 N 个订单有 1
个客户,因此每个订单都包含一个指向其所属客户的外键。这是“连接”,这意味着订单“拥有”(或字面上包含)连接(信息)。这与 OO/模型世界完全相反。

这可能有助于理解:

public class Customer {     // This field doesn''t exist in the database     // It is simulated with a SQL query     // "OO speak": Customer owns the orders     private List<Order> orders;}public class Order {     // This field actually exists in the DB     // In a purely OO model, we could omit it     // "DB speak": Order contains a foreign key to customer     private Customer customer;}

反面是对象的OO“所有者”,在这种情况下是客户。客户在表中没有用于存储订单的列,因此您必须告诉它可以在订单表中的哪个位置保存此数据(通过
发生mappedBy)。

另一个常见的例子是树的节点既可以是父母也可以是孩子。在这种情况下,这两个字段在一个类中使用:

public class Node {    // Again, this is managed by Hibernate.    // There is no matching column in the database.    @OneToMany(cascade = CascadeType.ALL) // mappedBy is only necessary when there are two fields with the type "Node"    private List<Node> children;    // This field exists in the database.    // For the OO model, it''s not really necessary and in fact    // some XML implementations omit it to save memory.    // Of course, that limits your options to navigate the tree.    @ManyToOne    private Node parent;}

这就解释了“外键”多对一的设计作品。还有第二种方法,它使用另一个表来维护关系。这意味着,对于我们的第一个示例,您有三个表:一个包含客户,一个包含订单,以及一个包含一对主键(customerPK、orderPK)的两列表。

这种方式比上面的方式更加灵活(可以轻松处理一对一、多对一、一对多甚至多对多)。价格是这样

  • 它有点慢(必须维护另一个表并且连接使用三个表而不是两个),
  • 连接语法更复杂(如果您必须手动编写许多查询,例如当您尝试调试某些东西时,这可能会很乏味)
  • 它更容易出错,因为当管理连接表的代码出现问题时,您可能会突然得到太多或太少的结果。

这就是为什么我很少推荐这种方法。

@ ManyToMany / @ OneToMany mappingby属性用于双向关联

@ ManyToMany / @ OneToMany mappingby属性用于双向关联

我正在为我的实习工作开发JPA兼容套件…该套件的一部分涉及测试极端情况的正确实现。

@ManyToMany具有mapedBy属性。JPA指出:

字符串mappingBy-拥有关系的字段或属性。除非关系是单向的,否则为必需。

没有给出默认值-默认列为空。

给定双向@ManyToMany-此示例来自JPA 2.0 JSR-317规范本身!

顾客

@ManyToMany@JoinTable(name="CUST_PHONES")public Set<PhoneNumber> getPhones() { return phones; }

电话号码

@ManyToMany(mappedBy="phones")public Set<Customer> getCustomers() { return customers; }

尚未在@ManyToManyof的中定义mapledBy属性Customer!我不知道的双向映射有默认值吗?

我查看了类似的情况,发现: @OneToOne-mappingBy是可选的,没有默认值
@OneToMany-完全相同@ManyToMany(mappedBy对于双向是可选的,没有默认值)

简而言之,我的问题是:
对于@ManyToMany@OneToMany,应在关系的拥有方(Customer例如)中将其放置在mappedBy属性中?

答案1

小编典典

这绝不是一个极端的情况。每个双向关联都有一个所有者方和一个反向方。

JPA使用拥有方来确定两个实体之间是否存在关联。另一侧被忽略。

拥有方定义了如何映射关联(使用JoinColumn,JoinTable等批注)。它没有任何mappedBy属性。

反面使用该mappedBy属性说:“嘿,我只是由以下属性映射的那个的逆关联”。

因此,根据定义,拥有方没有mappedBy属性。如果有一个,它就不会是拥有者。

JPA规范对此做了很好的解释。如果您需要为此规范构建兼容套件,则最好阅读并理解它。

我真的看不出编写这种兼容工具包的意义,因为正如在JPA2
JSR主页上所写的那样,

根据Java规范参与协议(JSPA)的要求,Java Persistence API版本2.0
TCK将免费获得许可,无需支持合格的非营利实体。此类资格将由兼容性测试奖学金计划进行验证。经奖学金委员会批准,也可以免费提供支持。有关更多信息,请访问:http
//java.sun.com/scholarship/。

@ManyToOne JPA 关联的 CascadeType.ALL 是什么意思

@ManyToOne JPA 关联的 CascadeType.ALL 是什么意思

我想我误解了在关系中级联的含义@ManyToOne

案子:

public class User {

   @OneToMany(fetch = FetchType.EAGER)
   protected Set<Address> userAddresses;

}

public class Address {

   @ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
   protected User addressOwner;

}

的含义是cascade = CascadeType.ALL什么?例如,如果我从数据库中删除某个地址,我添加的事实如何cascade = CascadeType.ALL影响我的数据(User我猜是)?

@ManyToOne JPA关联和级联…不确定删除对象会发生什么

@ManyToOne JPA关联和级联…不确定删除对象会发生什么

对于删除操作中级联的工作方式,我仍然不太清楚。我想知道如果我有这个会发生什么:

class myBean{

    @ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
        public Cliente getClienteDiAppartenenza() {
            return clienteDiAppartenenza;
        }

}


class Cliente{
@OneToMany(cascade = CascadeType.ALL,orphanRemoval = true,fetch = FetchType.LAZY)
    public List<myBean> getMyBeans() {
        return myBeans;
    }
}

如果我删除具有此属性的myBean,我不确定链接的Cliente是否也会被删除(很奇怪),或者Cliente内部的集合将被更新,并且myBean的实例将被删除,然后保存。

会发生什么??Hibernato文档对此不太清楚…

@OneToMany、@ManyToOne以及@ManyToMany讲解

@OneToMany、@ManyToOne以及@ManyToMany讲解

一、一对多(@OneToMany)
1、单向一对多模型
假设通过一个客户实体可以获得多个地址信息。
对于一对多的实体关系而言,表结构有两种设计策略,分别是外键关联和表关联。
(1) 映射策略---外键关联
在数据库中表customer和表结构address定义,如下:

create table customer (
  id int(20) not null auto_increment,
  name varchar(100),
  primary key(id)
)
 
create table address (
  id int(20) not null auto_increment,
  province varchar(50),
  city varchar(50),
  postcode varchar(50),
  detail varchar(50),
  customer_id int(20),
  primary key (id)
)


注意此时外键定义在多的一方,也就是address表中。

 此时,表customer映射为实体CustomerEO,代码如下:

@Entity
@Table (name="customer")
public class CustomerEO implements java.io.Serializable {
  @OneToMany(cascade={ CascadeType.ALL })
  @JoinColumn(name="customer_id")
  private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
 ...
}

注释@OneToMany的定义代码如下: 

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToMany {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fetch() default LAZY;
  String mappedBy() default "";
}

使用时要注意一下几点问题: 

a、targetEntity属性表示默认关联的实体类型。如果集合类中指定了具体类型了,不需要使用targetEntity.否则要指定targetEntity=AddressEO.class。 
b、mappedBy属性用于标记当实体之间是双向时使用。 

(2) 映射策略---表关联 
在上面address表中去掉customer_id字段,在增加一个表ref_customer_address,如下: 

--客户地址关系表
create table ref_customer_address (
  customer_id int(20) not null,
  address_id int(20) not null unique
)

此时表customer映射为CustomerEO实体,代码如下: 

@Entity
@Table(name = "customer")
public class CustomerEO implements java.io.Serializable {
  ...
  @OneToMany(cascade = { CascadeType.ALL })
  @JoinTable(name="ref_customer_address",
           joinColumns={ @JoinColumn(name="customer_id",referencedColumnName="id")},
           inverseJoinColumns={@JoinColumn(name="address_id",referencedColumnName="id")})
  private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
  ...
}

表关联@JoinTable,定义如下: 

@Target({METHOD,FIELD}) 
public @interface JoinTable {
  String name() default "";
  String catalog() default "";
  String schema() default "";
  JoinColumn[] joinColumns() default {};
  JoinColumn[] inverseJoinColumns() default {};
  UniqueConstraint[] uniqueConstraints default {};
}

其中:
a、该标记和@Table相似,用于标注用于关联的表。
b、name属性为连接两张表的表名。默认的表名为:“表名1”+“-”+“表名2”,上面例子默认的表名为customer_address。
c、joinColumns属性表示,在保存关系中的表中,所保存关联的外键字段。
d、inverseJoinColumns属性与joinColumns属性类似,不过它保存的是保存关系的另一个外键字段。

(3) 默认关联
在数据库底层为两张表添加约束,如下:

create table customer_address (
  customer_id int(20) not null,
  address_id int(20) not null unique
)
alter table customer_address add constraint fk_ref_customer foreign key (customer_id) references customer (id);
 
alter table customer_address add constraint fk_ref_address foreign key (address_id) references address (id);

这样,在CustomerEO中只需要在标注@OneToMany即可!


二、多对一@ManyToOne
1、单向多对一模型。
(1) 外键关联
配置AddressEO实体如下:

@Entity
@Table(name="address")
public class AddressEO implements java.io.Serializable {
     
  @ManyToOne(cascade = { CascadeType.ALL })
  @JoinColumn(name="customer_id")
  private CustomerEO customer;
     
  // ...
}

@ManyToOne定义如下:

@Target({METHOD,FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fatch() default EAGER;
  boolean optional() default true;
}

(2) 默认关联
数据库脚本定义的相关字段的约束,创建外键后,直接使用@ManyToOne

三、高级一对多和多对一映射
即双向关联模型,确定了双向关联后,多的一方AddressEO不变使用@ManyToOne,而CustomerEO实体修改为:

@Entity
@Table(name="customer")
public class CustomerEO {
     
  @OneToMany(mappedBy="customer")
  private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
     
  // ...
}

其中,@OneToMany标记中的mappedBy属性的值为AddressEO实体中所引用的CustomerEO实体的属性名。 

四、多对多(@ManyToMany)
和一对多类型,不在赘述。@ManyToMany标记的定义如下:

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToMany {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fecth() default LAZY;
  String mappedBy() default "";
}

五、最后,谈谈关于集合类的选择
在映射关系中可以使用的集合类有Collection、Set、List和Map,下面看下如何选择。
1、定义时使用接口,初始化使用具体的类。
如Collection可以初始化为ArrayList或HashSet;
Set可以初始化为HashSet;
List可以初始化为ArrayList;
Map可以初始化为HashMap.
2、集合类的选择
Collection类是Set和List的父类,在未确定使用Set或List时可使用;
Set集合中对象不能重复,并且是无序的;
List集合中的对象可以有重复,并且可以有排序;
Map集合是带有key和value值的集合。


我们今天的关于什么是双向 JPA OneToMany/ManyToOne 关联中的“关联的反面”?双向关联是什么意思的分享已经告一段落,感谢您的关注,如果您想了解更多关于@ ManyToMany / @ OneToMany mappingby属性用于双向关联、@ManyToOne JPA 关联的 CascadeType.ALL 是什么意思、@ManyToOne JPA关联和级联…不确定删除对象会发生什么、@OneToMany、@ManyToOne以及@ManyToMany讲解的相关信息,请在本站查询。

本文标签: