Hibernate注解符合主键关联关系、持久化传播、继承映射

组件属性包含的关联实体

前面已经提到过,组件里的属性不仅可以是基本类型、字符串、日期类型等,也可以是值类型行

的组件,甚至可以是关联实体。

对于组件的属性是关联实体的情形,可以使用@OneToOne、@ OneToMany、@ManyToOne

@ ManyToMany修饰代表关联实体的属性。如果程序采用基于外键的映射策略,还需要配合

@ loinColumn注解——该注解用于映射外键列:如果程序采用基于连接表的映射策略,还需要配@ JoinTable注解—该注解用于映射连接表

下面的 Person实体定义包含一个 Address类型的属性,但这个 Address类型的属性并非代表关,只是一个组件

@Entity

@Table(name="person_inf")

public class Person {

  

  

   //标识属性

     @Id @Column(name="person_id")

     @GeneratedValue(strategy=GenerationType.IDENTITY)

     private Integer id;

     //定义一个组件

     private Address address;

}

上面程序中粗体字代码定义了 Address类型的组件属性, Address组件中包含了一个Set类型的属性,该Set类型的属性负责维护与 School实体之间的1-N关联。

       如果程序使用不带连接表的关联策略来维护 Address与 School之间的关联关系,则需要使用aoneToMany、 @JoinColum修饰代表关联实体的Set属性。

       如果程序使用带连接表的关联策略来维护 Address与 School之间的关联关系,则需要使用@OneToMany、@ JoinTable修饰代表关联实体的set属性

下面使用不带连接表的关联策略来维护Adess与 School之间的关联关系,因此需要使用@OneToMany、@ JoinColumn修饰 Address里代表关联实体的set属性。下面是Adess类的源代码。

@Entity

@Table(name="address_inf")

public class Address {

  

   Id @Column(name="address_inf")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private int addressId;

   //定义地址详细信息的成员变量

   private String addressDetail;

   //定义该组件属性所在的包含实体

   @parent

   @OneToMany(targetEntity=School.class)

   //映射外键列,此处告诉Hibernate在school实体对应的表中增加外键列

   //该外键列的列名为address_id,参照person_inf表 的person_id主键列

@JoinColumn(name="address_id",referencedColumnName="person_id")

   private Set<School> schools = new HashSet<>();

}

下面师范如何保存Person对象和Address对象

//保存 Person和 Schoo1对象

private void test Person (

Session session- Hibernateutil currentsession ()

Transaction tx- session. beginTransaction ( )i

//创建一个 Person对象

Person p= new Person (

为 crazyit

//设置 Person的

name

P setName("crazyit")i

p staGe(21)i

session. save(p)i

//创建一个 Address对象

Address a= new Address("广州天河")

/设置 Person对象的 Address属性

p. setAddress (a)i

//创建两个 Schoo1对象

School s1= new Schoo1("疯狂os训练营”);

Schoo1s2= new Schoo1("疯狂Java训练营”)

//保存两个 Schoo1实体

session. save(s1)i

session. save(s2)i

//设置 Address对象和两个 Schoo1的关联关系

a. getSchools().add(sl)i

a.getschools ().add(s2)i

tx commitor

Hibernateutil.closesession()

基于符合主键的关联关系

对于1-N的双向关联,1的一端将两个属性结合起来作为符合主键,N的一端依然使用Integer类型的普通主键。

       下面是1的一端的源码

@Entity

@Table(name="person_inf")

public class Person implements java.io.Serializable{

   //定义first成员变量,作为标识属性的成员

   private String first;

   //定义last成员变量,作为标识属性的成员

   @Id

   private String last;

   //记录该Person实体关联的所有Address实体

@OneToMany(targetEntity=Address.class,mappedBy="person",cascade=CascadeType.All)

   private Set<Address> addresses = new HashSet<>();

//重写equals和hashCode方法

}

下面是Address实体类的代码

@Entity

@Table(name="address_inf")

public class Address {

  

   Id @Column(name="address_inf")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private int addressId;

   //定义地址详细信息的成员变量

   private String addressDetail;

   //定义该组件属性所在的包含实体

   @ManyToOne(targetEntity=Person.class)

   //使用@JoinColumns包含多个@JoinColumn定义外键列

   @JoinColumns({//由于主表使用了符合主键(有两个主键列)

   //因此需要使用两个@JoinColumn定义外键列来参照person_inf表的两个主键列

   @JoinColumn(name="person_first",referencedColumnName="first",nullable=false),

   @JoinColumn(name="person_last",referencedColumnName="last",nullable=false)

   })

   private Person person;

}

复合主键的成员属性为关联实体

例如:订单,商品,订单项

一个订单包含多个订单项,一个订单项用于订购某个商品,以及订购数量,一个商品可以多次出现在不同的订单中

       Product类没有保留与其他实体的关联关系

@Entity

@Table(name="product_id")

public class Product {

   //定义标识属性

   @Id @Column(name="product_id")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Integer productId;

   private String name;

   //五参数的构造器

   public Product() {}

   //

}

Order持久化类

OrderItem需要维护与订单项的1-N关联关系,因策Order类中需要增加Set类型的属性,该属性负责管理与多个OrderItem之间的关联关系,应该使用@OneToMany修饰该Set集合属性

@Entity

@Table(name="order_inf")

public class Order {

   //定义标识属性

     @Id @Column(name="product_id")

     @GeneratedValue(strategy=GenerationType.IDENTITY)

     private Integer orderId;

     private Date orderDate;

     //关联的订单项

   @OneToMany(targetEntity=OrderItem.class,mappedBy="order")

     private Set<OrderItem> items = new HashSet<>();

}

OrderItem需要维护与Product的N-1关联关系,还需要维护与Order之间的N-1关联关系,因此使用@ManyToOne修饰这两个代表关联实体的属性,并配置@JointColumn来映射底层的外键列

下面是OrderItem的实体

@Entity

@Table(name="order_item_inf")

public class OrderItem implements java.io.Serializable{

   //下面三个属性将作为联合主键

   //定义关联的Order实体

   @ManyToOne(targetEntity=Order.class)

   //映射名为order_id的外键列,参照order_inf的order_id主键列

@JoinColumn(name="order_id",referencedColumnName="order_id")

   @Id

   private Order order;

   //定义关联的Product实体

   @ManyToOne(targetEntity=Product.class)

   //映射名我product_id的外键列,参照product_inf的product_id主键列

@JoinColumn(name="product_id",referencedColumnName="product_id")

   @Id

   private Product product;

private Product product;

   //该订单订购的产品数量

   @Id

   private int count;

  

   //有无参数构造器  重写equals方法和hashcode方法

}

持久化的传播性

       正如在前面的程序中看到的,当程序中有两个关联实体时,程序需要主动保存、除或重关个化实体:如果需要处理许多彼此关联的实体,则需要依次保存每个实体,这会让人感觉机点

从数据库建模的角度来看,两个表之间的1-N关联关系总是用外键约束米表示,其中保留外键的表称为从表,被从表参照的数据表称为主表,对于这种主从表约束关系, Hibemate则们两种映射策略。

1>将从表记录映射成持久化类的组件

2>将从表记录映射成持久化类的实体

将从表记录映射成持久化类的组件,这些组件的生命周期总是依赖于父对象, Hibernate会默

联操作,不需要额外的动作。当父对象被保存时,这些组件子对象也将被保存,父对象被删除,子对象也将被删除

       如果将从表记录映射成持久化实体,则从表实体也有了自己的生命周期,从而应该允许其他实体共对它的引用,例如,从集合中移除一个实体,不意味着它可以被酬除。所以 Hibernate默认不启用实其他关联实体之间的级联操作

       对于关联实体面言, Hibernate默认不会启用级联操作,当父对象被保存时,它关联的子实体不会保存:父对象被删除时,它关联的子实体不会被删除,为了启用不同持久化操作的级联行为, Hibernate定义了如下级联风格

1>CascadeType .ALLt指定 Hibernate将所有的持久化操作都级联到关联实体

2>CascadeType .MERGE:指定 Hibemate将 merge操作级联到关联实体

3>CascadeType .PERSIST:指定 Hibernate将pet操作级联到关联实体

4>CascadeType.REFRESH:指定 Hibernate将resh操作级联到关联实体

5>CascadeType.REMOVE:指定 Hibernate将 remove操作级联到关联实体

如变程序着望某个操作能被级联传播到关联实体,则可以在配置@ OneToMany、@One ToOne、@MenyToMany时通过 cascade属性来指定,例如:

//指定persist操作将级联到关联实体

@OneToOne(cascade=CascadeType.PERSIST)

级联风格是可组合的,如下面配置所示:

//指定persist()操作将级联关联到实体

@OneToOne(cascade={ CascadeType.PERSIST, CascadeType, DELTE})

可以使用 cascade= CascadeType.ALL指定所有的持久化操作都被级联到关联实体。 Hibernate对关联实体默认不使用任何级联,即任何操作都不会被级联到关联实体,

Hibernate还支持一个特殊的级联策略:删除“孤儿”记录(可通过 @oneToMany, @One ToOne的orphanRemoval属性来启动该级联策略),该级联策略只对当前实体是1的一端,且底层数据表为主表有效,对于启用了 ophanRemoval策略的级联操作而言,当程序通过主表实体切断与从表实体的关联关系时,虽然此时主表实体对应的记录井没有删除,但由于从表实体失去了对主表实体的引用,因此这从表实体就变成了“孤儿”记录, Hibemate会自动删除这些记录

       对于级联的设定, Hibernate有如下建议

       1>在 ManyToOne中指定级联没什么意义,级联通常在 @OneToOne和@ OneToMany关系中比较有用---一因为级联操作应该是由主表记录传播到从表记录,通常从表记录则不应该传播到主表记录,因此 @ManyToOne不支持指定 cascade属性,但在某些极端情况下,如果程序就是希望为 @ManyToOne指定级联策略,则也可使用 Hibernate提供的 @cascade注解

////////////////期待完善中

猜你喜欢

转载自www.cnblogs.com/sundaysjava/p/10340385.html
今日推荐