最新公告
  • 欢迎您光临波比源码,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入我们
  • Hibernate之实体关系映射


    延迟加载与即时加载

    例如Person类和Email类是1对多关系,如果设为即时加载,当加载Person时,会自动加载Email,如果设置为延迟加载,当第1次调用person.getEmails()时才会履行SQL语句加载Email

    注解配置时,@OnetToMany(Fetch = FetchType.EAGER)为即时加载,Fetch = FetchType.LAZY为延迟加载

    延迟加载和即时加载的策略适用于所有1对多、多对1、多对多等所有的实体关系

    1般来讲,延迟加载要比即时加载节省资源,但是如果处理不当,延迟加载容易抛出LazyInitializationException异常,解决当方法有两种,1种是在Session关闭之前调用1下,person.getEmails()方法,逼迫Hibernate加载数据,这是最经常使用的方式,还有1种是延迟Session的范围,使Session关闭前完成所有的业务逻辑,在web程序中有些工具也能延长Session的范围,例如Spring的OpenSessionInViewFilter,能把Session扩大到所有的web资源,包括Servlet层、JSP层、DAO层、Service层

    单边1对多

    1方有集合属性,包括多个多方,而多方没有1方的援用

    import javax.persistence.*;

    //“1"方
    @Entity
    @Table(name="tb_person")
    public class Person{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    @OneToMany(fetch = FetchType.EAGER,targetEntity = Email.class,cascade={
    CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE, CascadeType.REFRESH
    })
    @JoinColumns(value= {@JoinColumn(name="person_id",referencedColumnName="id")})
    @OrderBy(value = “email desc")
    private List<Email> emails = new ArrayList<Email>();
    //在email对应的表中产生1个person_id字段,援用person标的id
    // referencedColumnName指的是实体类的关联列,默许为主键,可省略

    //setter、getter略
    }

    //“多"方
    @Entity
    @Table(name="tb_email")
    public class Email{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String email;

    //setter、getter略
    }

    <hibernate-mapping package="com.clf.hibernate.bean">
    <class name="Person" table="tb_person">
    <id name="id" column="id">
    <generator class="native">
    </id>
    <property name="name"/>
    <bag name="emails" cascade="all" lazy="false" where="email like %@%" order-by="email">
    <key column="email_id"></key>
    <one-to-many class="com.clf.hibernate.bean.Email" />
    </bag>
    </class>
    </ hibernate-mapping >

    <hibernate-mapping package="com.clf.hibernate.bean">
    <class name="Email" table="tb_eamil">
    <id name="id" column="id">
    <generator class="native">
    </id>
    <property name="email"/>
    </class>
    </ hibernate-mapping >

    如果集合属性使用的是Set而非List,则XML配置时需要使用<set>标签而不是<bag>标签,而且不能使用order-by属性

    JPA(Java Persistence API)要求实体类必须为POJO,而不能为String等基本类型,换句话说,电子邮件必须封装为Email对象,即便它只有1个String属性

    而XML配置允许直接使用String作为实体类,而不需要封装成1个Email对象

    配置改动以下

    <bag name="emails" cascade="all" lazy="false" where="email like %@%" order-by="email">
    <key column="email_id"></key>
    <element type="String" column="email" />
    </bag>

    单边多对1

    //“1"方
    @Entity
    @Table(name = "tb_table")
    public class Type{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(unique = true)
    private String name;
    //setter、getter方法略
    }
    //“多"方
    @Entity
    @Table(name = <span style="font-family: Arial, Helvetica, sans-serif;">"</span><span style="font-family: Arial, Helvetica, sans-serif;">tb_article")</span>
    public class Article{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToOne(cascade = {CascadeType.PERSIST},fetch = FetchType.EAGER)
    @JoinColumn(name = "type_id")
    Private Type type;
    //在article表总产生1个type_id字段,援用type表中的id字段

    @Column(columnDefinition = "text")
    private String content;

    private String name;

    //setter、getter方法略
    }

    <class name="Type" table="tb_type">
    <id name="id" column="id">
    <generator class="native">
    </id>
    <property name="name"/>
    </class>

    <class name="Article" table="tb_article">
    <id name="id" column="id">
    <generator class="native">
    </id>
    <property name="name"/>
    <property name="content"/>
    <many-to-one name = "type" column = "type_id" cascade = "persist" lazy="false" not-found="ignore">
    </ many-to-one >
    </class>

    双边多对1、1对多

    //“1"方
    @Entity
    @Table(name = "tb_class")
    public class Clazz{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    //使用反向配置(@ManyToOne不存在该属性),双边关系中,控制权1般交给多方,定义在被具有方,指向具有方,具有方能够级联地保护被具有方的关系。因此这里没有配置数据库的外键,而只配置了1个mappedBy属性,告知Hibernate,配置信息要到Student类的“clazz"属性中找
    @OneToMany(mappedBy = "clazz")
    private List<Student> students;

    //setter、getter方法略
    }

    //“多"方
    @Entity
    @Table(name = "tb_student")
    public class Student{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToOne(cascade = {CascadeType.PERSIST},fetch = FetchType.EAGER)
    @JoinColumn(name = "class_id")
    Private Clazz clazz;
    //在student表总产生1个class_id字段,援用class表中的id字段

    private String sex;

    private String name;

    //setter、getter方法略
    }

    <class name="Clazz" table="tb_class">
    <id name="id" column="id">
    <generator class="native">
    </id>
    <property name="name"/>
    <bag name="students" inverse="true" cascade="all">
    <key column="class_id"/>
    <one-to-many class="com.clf.hibernate.bean.Student"/>
    </bag>
    </class>

    <class name="Student" table="tb_student">
    <id name="id" column="id">
    <generator class="native">
    </id>
    <property name="name"/>
    <property name="sex"/>
    <many-to-one name = "clazz" column = "class_id" cascade = "all" >
    </ many-to-one >
    </class>

    单边1对1

    有两种策略可以实现1对1的关联映照

    主键关联:即让两个对象具有相同的主键值,以表明它们之间的逐一对应的关系;数据库表不会有额外的字段来保护它们之间的关系,仅通过表的主键来关联。

    唯1外键关联:外键关联,本来是用于多对1的配置,但是如果加上唯1的限制以后,也能够用来表示1对1关联关系。

    唯1外键关联策略

    @Entity
    public class IdCard {
    private int id;
    private String cardNo;

    @Id
    @GeneratedValue
    public int getId() {return id;}

    //setter、getter略
    }

    @Entity
    public class Person {

    private IdCard idCard;//援用IdCard对象
    private String name;

    @Id
    @GeneratedValue
    private int id;

    @OneToOne
    @JoinColumn(name="idCard")
    private IdCard idCard; //援用IdCard对象

    private String name;

    //setter、getter略
    }

    <class name="com.clf.hibernate.IdCard" table="t_idcard">
    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <property name="cardNo"/>
    </class>

    <class name="com.clf.hibernate.Person" table="t_person">
    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <property name="name"/>
    <!–在多的1端(当前Person1端),加入1个外键(当前为idCard)指向1的1端(当前IdCard),但多对1关联映照字段是可以重复的,所以需要加入1个唯1条件unique="true",这样就能够此字段唯1了。–>
    <many-to-one name="idCard" unique="true"/>
    </class>

    主键关联策略

    IdCart正常注解

    @Entity
    public class Person {

    private IdCard idCard;//援用IdCard对象
    private String name;

    @Id
    @GeneratedValue
    private int id;

    @OneToOne
    @PrimaryKeyJoinColumn //注解主键关联映照
    private IdCard idCard; //援用IdCard对象

    private String name;

    //setter、getter略
    }

    <class name="com.clf.hibernate.IdCard" table="t_idcard">
    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <property name="cardNo"/>
    </class>

    <class name="com.clf.hibernate.Person" table="t_person">
    <id name="id" column="id">
    <!–主键不是自己生成的,而是作为1个外键,所以使用foreign生成策略。foreign:使用另外1个相干联的对象的标识符,通常和<one-to-one>联合起来使用。再使用元素<param>的属性值指定相干联对象(这里Person相干联的对象为idCard,则标识符为idCard的id)为了能够在加载person数据同时加载IdCard数据,所以需要使用1个标签<one-to-one>来设置这个功能。 –>
    <generator class="foreign">
    <!– 元素<param>属性name的值是固定为property –>
    <param name="property">idCard</param>
    </generator>
    </id>
    <property name="name"/>
    <!–表示如何加载它的援用对象(这里援用对象就指idCard这里的name值是idCard),同时也说是1对1的关系。 默许方式是根据主键加载(把person中的主键取出再到IdCard中来取相干IdCard数据。) 我们也说过此主键也作为1个外键援用 了IdCard,所以需要加1个数据库限制(外键束缚)constrained="true" –>
    <one-to-one name="idCard" constrained="true"/>
    </class>

    联合主键关联(Annotation方式)

    实现上联合主键的原理同唯1外键关联-单向1样,只是使用的是@JoinColumns,而不是@JoinColumn,实体类注解以下:

    @OneToOne
    @JoinColumns(
    {
    @JoinColumn(name="personId", referencedColumnName="id"),
    @JoinColumn(name="personName", referencedColumnName="name")
    }
    )
    private Person person;

       注意:@JoinColumns注解联合主键1对1联系,然后再使用@JoinColumn来注解当前表中的外键字段名,并指定关联哪一个字段,使用referencedColumnName指定哪一个字段的名称

    双边1对1

    凡是双向关联,必设mappedBy

    唯1外键关联策略

    @Entity
    public class IdCard {

    private String cardNo;

    @Id
    @GeneratedValue
    private int id;

    @OneToOne(mappedBy="idCard")
    private Person person;

    //setter、getter略
    }

    @Entity
    public class Person {

    private IdCard idCard;//援用IdCard对象
    private String name;

    @Id
    @GeneratedValue
    private int id;

    @OneToOne
    @JoinColumn(name="idCard") //为idCard对象指定外键
    private IdCard idCard; //援用IdCard对象

    private String name;

    //setter、getter略
    }

    <class name="com.clf.hibernate.IdCard" table="t_idcard">
    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <property name="cardNo"/>
    <one-to-one name="person" property-ref="idCard"/>
    </class>
    <!– 1对1 唯1外键 关联映照 双向 需要在另外一端(当前IdCard),添加<one-to-one>标签,唆使hibernate如何加载其关联对象(或援用对象),默许根据主键加载(加载person),外键关联映照中,由于两个实体采取的是person的外键来保护的关系,所以不能指定主键加载person,而要根据person的外键加载,所以采取以下映照方式:
    <one-to-one>标签:告知hibernate如何加载其关联对象
    property-ref属性:是根据哪一个字段进行比较加载数据 –>

    <class name="com.clf.hibernate.Person" table="t_person">
    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <property name="name"/>
    <!–在多的1端(当前Person1端),加入1个外键(当前为idCard)指向1的1端(当前IdCard),但多对1关联映照字段是可以重复的,所以需要加入1个唯1条件unique="true",这样就能够此字段唯1了。–>
    <many-to-one name="idCard" unique="true"/>
    </class>

    主键关联策略

    @Entity
    public class IdCard {

    private String cardNo;

    @Id
    @GeneratedValue
    private int id;

    @OneToOne(mappedBy="idCard")
    private Person person;

    //setter、getter略
    }

    @Entity
    public class Person {

    private IdCard idCard;//援用IdCard对象
    private String name;

    @Id
    @GeneratedValue
    private int id;

    @OneToOne
    @PrimaryKeyJoinColumn //注解主键关联映照
    private IdCard idCard; //援用IdCard对象

    private String name;

    //setter、getter略
    }

    <class name="com.clf.hibernate.IdCard" table="t_idcard">
    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <property name="cardNo"/>
    <one-to-one name="person"/>
    </class>

    <class name="com.clf.hibernate.Person" table="t_person">
    <id name="id" column="id">
    <generator class="foreign">
    <param name="property">idCard</param>
    </generator>
    </id>
    <property name="name"/>
    <one-to-one name="idCard" constrained="true"/>
    </class>

    单边多对多

    @Entity
    public class User {
    private int id;
    private String name;
    private Set<User> roles = new HashSet<User>();// Role对象的集合 @Id

    @GeneratedValue
    public int getId() {return id;}

    @ManyToMany
    @JoinTable(name="u_r",//使用@JoinTable标签的name属性注解第3方表名称
    joinColumns={@JoinColumn(name="userId")},
    //使用joinColumns属性来注解当前实体类在第3方表中的字段名称并指向该对象
    inverseJoinColumns={@JoinColumn(name="roleId")}
    //使用inverseJoinColumns属性来注解当前实体类持有援用对象在第3方表中的字段名称并指向被援用对象表
    )
    public Set<User> getRoles() {return roles;
    }

    Role实体正常注解

    Role映照文件:

    <class name="com.clf.hibernate.Role" table="t_role">
    <id name="id">
    <generator class="native"/>
    </id>
    <property name="name" column="name"/>
    </class>

    User映照文件:
    <class name="com.clf.hibernate.User" table="t_user">
    <id name="id"column="id">
    <generator class="native"/>
    </id>
    <property name="name"/>
    <!–使用<set>标签映照集合(set),标签中的name值为对象属性名(集合roles),而使用table属性是用于生成第3方表名称,例:table="t_user_role",但是第3方面中的字段是自动加入的,作为外键分别指向其它表。
    所以表<key>标签设置,例:<key column="userid"/>,意思是:在第3方表(t_user_role)中加入1个外键并且指向当前的映照实体类所对应的表(t_user).使用<many-to-many>来指定此映照集合所对象的类(实例类),并且使用column属性加入1个外键指向Role实体类所对应的表(t_role) –>
    <set name="roles" table="t_user_role">
    <key column="userid"/>
    <many-to-many class="com.clf.hibernate.Role" column="roleid"/>
    </set>
    </class>

    双边多对多

    User实体类的注解与单边多对多1样

    Role实体类注解也非常的简单:使用@ManyToMany注解,并使用mappedBy属性指定援用对象持有自己的的属性名

    @Entity
    public class Role {
    private int id;
    private String name;
    private Set<User> users = new HashSet<User>();

    @Id
    @GeneratedValue
    public int getId() {return id; }

    @ManyToMany(mappedBy="roles")
    public Set<User> getUsers() {return users;}

    public voidsetUsers(Set<User> users) {this.users = users;
    }

    <class name="com.clf.hibernate.User" table="t_user">
    <id name="id"column="id">
    <generator class="native"/>
    </id>
    <property name="name"/>
    <set name="roles" table="t_user_role">
    <key column="userid"/>
    <many-to-many class="com.clf.hibernate.Role" column="roleid"/>
    </set>
    </class>

    <class name="com.clf.hibernate.Role" table="t_role">
    <id name="id">
    <generator class="native"/>
    </id>
    <property name="name" column="name"/>
    <set name="users" table="t_user_role"order-by="userid">
    <key column="roleid"/>
    <many-to-many class="com.clf.hibernate.User" column="userid"/>
    </set>
    </class>

    component(组件)关联映照

    例如有以下两个实体类:用户与员工,二者存在很多相同的字段,但是二者有不可以是同1个类,这样在实体类中每次都要输入很多信息,现在把其中共有部份抽取出来成为1个类,然后在用户、员工对象中援用就能够

    值对象没有标识,而实体对象具有标识,值对象属于某1个实体,使用它重复使用率提升,而且更清析。

    以上关系的映照称为component(组件)关联映照

    在hibernate中,component是某个实体的逻辑组成部份,它与实体的根本区分是没有oid,component可以成为是值对象(DDD)。

    采取component映照的好处:它实现了对象模型的细粒度划分,层次会更加分明,复用率会更高。

    <class name="com.clf.hibernate.User" table="t_user">
    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <property name="name" column="name"/>
    <component name="contact">
    <property name="email"/>
    <property name="address"/>
    <property name="zipCode"/>
    <property name="contactTel"/>
    </component>
    </class>
    @Entity
    public class User {
    private int id;
    private String name;
    private Contact contact;//值对象的援用

    @Id
    @GeneratedValue
    public int getId() { return id;}

    @Embedded//用于注解组件映照,表示嵌入对象的映照
    public Contact getContact() {return contact;}
    public void setContact(Contactcontact) {this.contact = contact;}

    Contact类是值对象,不是实体对象,是属于实体类的某1部份,因此没有映照文件

    Contact值对象:

    public class Contact {
    private String email;
    private String address;
    private String zipCode;
    private String contactTel;
    //setter、getter略
    }

    继承关联映照

    继承映照:就是把类的继承关系映照到数据库里(首先正确的存储,再正确的加载数据)

    继承关联映照的分类:

    单表继承:每棵类继承树使用1个表(table per class hierarchy)

    具体表继承:每一个子类1个表(table per subclass)

    类表继承:每一个具体类1个表(table per concrete class)(有1些限制)

    下面用1个实例来讲明3种继承关系的用法和区分:

    动物Animal有3个基本属性,然后有1个Pig继承了它并扩大了1个属性,还有1个Brid也继承了并且扩大了1个属性

     

    Animal实体类:

    public class Animal {
    private int id;
    private String name;
    private boolean sex;
    public int getId() {return id; }
    public void setId(int id) { this.id = id;}
    public String getName() {return name;}
    public void setName(Stringname) {this.name = name;}
    public boolean isSex() {return sex;}
    public void setSex(boolean sex) {this.sex = sex;}
    }

    Pig实体类:

    public class Pig extends Animal {
    private int weight;
    public int getWeight() {return weight;}
    public void setWeight(int weight) {this.weight = weight;}
    }

    Bird实体类:

    public class Bird extends Animal {
    private int height;
    public int getHeight() {return height;}
    public void setHeight(int height) {this.height = height;}
    }

    单表继承

    把所有的属性都要存储表中,目前最少需要5个字段,另外需要加入1个标识字段(表示哪一个具体的子类)

     

    其中:

               ①、id:表主键

               ②、name:动物的姓名,所有的动物都有

               ③、sex:动物的性别,所有的动物都有

               ④、weight:只有猪才有

               ⑤、height:只有鸟才有

               ⑥、type:表示动物的类型;P表示猪;B表示鸟

    <class name="Animal" table="t_animal" lazy="false">
    <id name="id">
    <generator class="native"/>
    </id>
    <discriminator column="type" type="string"/>
    <property name="name"/>
    <property name="sex"/>
    <subclass name="Pig" discriminator-value="P">
    <property name="weight"/>
    </subclass>
    <subclass name="Bird" discriminator-value="B">
    <property name="height"/>
    </subclass>
    </class>

    父类用普通的<class>标签定义

    在父类中定义1个discriminator,即指定这个辨别的字段的名称和类型,如:<discriminator column="XXX" type="string"/>

    子类使用<subclass>标签定义,在定义subclass的时候,需要注意以下几点:

    Subclass标签的name属性是子类的全路径名

    在Subclass标签中,用discriminator-value属性来标明本子类的discriminator字段(用来辨别不同类的字段)  的值Subclass标签,既可以被class标签所包括(这类包括关系正是表明了类之间的继承关系),也能够与class标  签平行。 当subclass标签的定义与class标签平行的时候,需要在subclass标签中,添加extends属性,里面的值
     是父类的全路径名称。子类的其它属性,像普通类1样,定义在subclass标签的内部。

    annotation注解

    父类中注解以下:

    使用@Inheritance注解为继承映照,再使用strategy属性来指定继承映照的方式

    strategy有3个值:InheritanceType.SINGLE_TABLE           单表继承

                      InheritanceType.TABLE_PER_CLASS       类表继承

                      InheritanceType.JOINED                具体表继承

    再使用@DiscriminatorColumn注意标识字段的字段名,及字段类型

    在类中使用@DiscriminatorValue来注解标识字段的值

    @Entity
    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(
    name="discriminator",
    discriminatorType=DiscriminatorType.STRING)
    @DiscriminatorValue("type")
    public class Animal {……}

    继承类中注解以下:

        只需要使用@DiscriminatorValue来注解标识字段的值

    具体表继承

    每一个类映照成1个表(table per subclass),所以Animal也映照成1张表(t_animal),表中字段为实体类属性

    而pig子类也需要映照成1张表(t_pid),但为了与父类联系需要加入1个外键(pidid)指向父类映照成的表(t_animal),字段为子类的扩大属性。Bird子类一样也映照成1张表(t_bird),也加入1个外键(birdid)指向父类映照成的表(t_animal),字段为子类的扩大属性。

    <class name="com.clf.hibernate.Animal" table="t_animal">
    <id name="id"column="id"><!– 映照主键 –>
    <generator class="native"/>
    </id>
    <property name="name"/><!– 映照普通属性 –>
    <property name="sex"/>
    <!–joined-subclass标签:每一个类映照成1个表 –>
    <joined-subclass name="com.clf.hibernate.Pig" table="t_pig">
    <!– <key>标签:会在相应的表(当前映照的表)里,加入1个外键 , 参照指向当前类的父类(当前Class标签对象的表(t_animal))–>
    <key column="pigid"/>
    <property name="weight"/>
    </joined-subclass>
    <joined-subclass name="com.clf.hibernate.Bird" table="t_bird">
    <key column="birdid"/>
    <property name="height"/>
    </joined-subclass>
    </class>

    这类策略是使用joined-subclass标签来定义子类的。父类、子类,每一个类都对应1张数据库表。

    在父类对应的数据库表中,实际上会存储所有的记录,包括父类和子类的记录;在子类对应的数据库表中,这个表只定义了子类中所独有的属性映照的字段。子类与父类,通过相同的主键值来关联。实现这类策略的时候,有以下步骤:

    父类用普通的<class>标签定义便可

    父类不再需要定义discriminator字段

    子类用<joined-subclass>标签定义,在定义joined-subclass的时候,需要注意以下几点:

    Joined-subclass标签的name属性是子类的全路径名

    Joined-subclass标签需要包括1个key标签,这个标签指定了子类和父类之间是通过哪一个字段来关联的。如:<key column="PARENT_KEY_ID"/>,这里的column,实际上就是父类的主键对应的映照字段名称。Joined-subclass标签,既可以被class标签所包括(这类包括关系正是表明了类之间的继承关系),也能够与class标签平行。 当Joined-subclass标签的定义与class标签平行的时候,需要在Joined-subclass标签中,添加extends属性,里面的值是父类的全路径名称。子类的其它属性,像普通类1样,定义在joined-subclass标签的内部。

    annotation注解

    由于子类生成的表需要援用父类生成的表,所以只需要在父类设置具体表继承映照就能够了,其它子类只需要使用@Entity注解就能够了

    @Entity
    @Inheritance(strategy=InheritanceType.JOINED)
    public class Animal {……}

    具体表继承效力没有单表继承高,但是单表继承会出现过剩的庸于字段,具体表层次分明

    类表继承

    每一个具体类(Pig、Brid)映照成1个表(table per concrete class)(有1些限制)

    <class name="com.clf.hibernate.Animal" table="t_animal">
    <id name="id"column="id"><!– 映照主键 –>
    <generator class="assigned"/><!– 每一个具体类映照1个表主键生成策略不可以使用native –>
    </id>
    <property name="name"/><!– 映照普通属性 –>
    <property name="sex"/>
    <!–使用<union-subclass>标签来映照"每一个具体类映照成1张表"的映照关系,实现上上面的表t_animal虽然映照到数据库中,但它没有任何作用。 –>
    <union-subclass name="com.clf.hibernate.Pig" table="t_pig">
    <property name="weight"/>
    </union-subclass>
    <union-subclass name="com.clf.hibernate.Bird" table="t_bird">
    <property name="height"/>
    </union-subclass>
    </class>

    如果不想t_animal存在(由于它没有实际的作用),可以设置<class>标签中的abstract="true"(抽象表),这样在导出至数据库时,就不会生成t_animal表了

    这类策略是使用union-subclass标签来定义子类的。每一个子类对应1张表,而且这个表的信息是完备的,即包括了所有从父类继承下来的属性映照的字段(这就是它跟joined-subclass的不同的地方,joined-subclass定义的子类的表,只包括子类特有属性映照的字段)。实现这类策略的时候,有以下步骤:

    父类用普通<class>标签定义便可

    子类用<union-subclass>标签定义,在定义union-subclass的时候,需要注意以下几点:

    Union-subclass标签不再需要包括key标签(与joined-subclass不同)

    Union-subclass标签,既可以被class标签所包括(这类包括关系正是表明了类之间的继承关系),也能够与class标签平行。 当Union-subclass标签的定义与class标签平行的时候,需要在Union-subclass标签中,添加extends属性,里面的值是父类的全路径名称。子类的其它属性,像普通类1样,定义在Union-subclass标签的内部。这个时候,虽然在union-subclass里面定义的只有子类的属性,但是由于它继承了父类,所以,不需要定义其它的属性,在映照到数据库表的时候,仍然包括了父类的所有属性的映照字段。

    注意:在保存对象的时候id是不能重复的(不能使用自增生成主键)

    annotation注解

    只需要对父类进行注解就能够了,由于子类表的ID是不可以重复,所以1般的主键生成策略已不适应了,只有表主键生成策略。

    首先使用@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)来注解继承映照,并且使用具体表继承方式,使用@TableGenerator来申明1个表主键生成策略再在主键上@GeneratedValue(generator="t_gen", strategy=GenerationType.TABLE)来注解生成策略为表生成策略,并且指定表生成策略的名称继承类只需要使用@Entity进行注解就能够了

    @Entity
    @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
    @TableGenerator(
    name="t_gen",
    table="t_gen_table",
    pkColumnName="t_pk",
    valueColumnName="t_value",
    pkColumnValue="person_pk",
    initialValue=1,
    allocationSize=1
    )

    3种继承关联映照的区分:

    第1种:它把所有的数据都存入1个表中,优点:效力好(操作的就是1个表);缺点:存在庸于字段,如果将庸于字段设置为非空,则就没法存入数据;

    第2种:层次分明,缺点:效力不好(表间存在关联表)

    第3种:主键字段不可以设置为自增主键生成策略。

    波比源码 – 精品源码模版分享 | www.bobi11.com
    1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
    2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
    3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
    4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
    5. 如有链接无法下载、失效或广告,请联系管理员处理!
    6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
    7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!

    波比源码 » Hibernate之实体关系映射

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    波比源码
    一个高级程序员模板开发平台
    升级波友尊享更多特权立即升级