Hibernate4学习总结(3)--注解形式的基础映射,主键映射,基本属性映射,复合属性映射,继承映射。

来源:互联网 发布:淘宝势力周多久一次 编辑:程序博客网 时间:2024/04/30 08:52

      Hibernate Annotation即hibernate注解,可以通过另一种方式将持久化类转化成表的相关信息,可以简化hibernate的配置文件。本文主要对Hibernate的注解进行讲解,由于篇幅原因,将注解部分分为两篇文章来写。集合映射和关联关系映射将在后面一文讲解。本文包括以下五个部分:

  1. 基础映射。
  2. 主键映射。
  3. 基本属性映射。
  4. 复合属性映射。
  5. 继承映射。

一、基础映射(注解加在持久化类上面)

  1.1到1.4的注解都是JPA的注解,1.5是hibernate的注解。

1.1 @Entity: 将POJO转化成持久化类。

1.2 @Table: 把持久化类转化成表的相关信息,@Table注解当中有以下几个属:

  • name: 指定表名。
  • schema: 指定将数据表存入哪个数据库。
  • catalog: 指定将数据表存入哪个数据库。
  • indexes: 指定表的引索列.
  • uniqueConstraints: 指定唯一约束。

1.3 indexes : @Index(columnList="数据表中的列名", name="索引名")。用于创建表的索引。

indexes={@Index(columnList="name", name="IDX_NAME"),         @Index(columnList="address", name="IDX_ADDRESS")}
1.4   uniqueConstraints : @UniqueConstraint(columnNames={"列名","列名"}, name="唯一约束名")。用于多列建立联合唯一约束。

uniqueConstraints={@UniqueConstraint(columnNames={"name", "age"}, name="UC_NAME_AGE")})
1.5 hibernate注解

  • @DynamicInsert:动态插入,根据持久化对象的属性是否有值明确生成insert语句。
  • @DynamicUpdate:动态修改,它会判断持久化对象中属性,哪些属性值发生了改变就会生成update的语句。(持久化状态下做修改)
  • @SelectBeforeUpdate:修改之前先查询,查询得到持久化对象再与脱管状态下的对象进行比较,哪些属性值发生了改变就会生成update的语句。(脱管状态下做修改)

例如:User实体类

package edu.scut.a_BasicMapping;import javax.persistence.*;import org.hibernate.annotations.DynamicInsert;import org.hibernate.annotations.DynamicUpdate;import org.hibernate.annotations.SelectBeforeUpdate;@Entity//将POJO类转化成持久化类@Table(name="USER_INFO",//指定表名   catalog="day33b",//指定创建到哪个数据库   //schema="day33b",//指定创建到哪个数据库,和catalog指定一个即可   indexes={@Index(columnList="name",name="IDX_NAME"),@Index(columnList="address",name="IDX_ADDRESS")},//创建表的索引   uniqueConstraints={@UniqueConstraint(columnNames={"name","age"},name="UC_NAME_AGE")}) //多列联合唯一约束//三个hibernate注解//@DynamicInsert(true) //动态插入,根据持久化对象的属性是否有值,生成相应的Sql语句//@DynamicUpdate(true) //动态修改,会判断持久化对象中的属性,那些属性改变,才会生成相应的update语句(持久化状态下做修改)@SelectBeforeUpdate(true) //修改之前先进行查询,查询得到持久化对象与脱管状态下的对象进行比较,那些属性改变生成sql语句。public class User {@Idprivate int id;private String name;private int age;private String address;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}}

生成的表user_info信息:


二、主键映射

2.1 主键生成策略

 @GeneratorValue(strategy=GenerationType.xxx)

  • GenerationType.AUTO:让Hibernate根据数据库方言自动选择主键生成策略。
  • GenerationType.IDENTITY: 适宜MySQL、SqlServer有自增长列的数据库。
  • GenerationType.SEQUENCE:适宜Oracle这种没有自增长有sequence的数据库。
  • GenerationType.TABLE: 适宜所有的数据库,因为它会单独生成一张表来维护主键生成。

例如:User.实体类

package edu.scut.b_PrimaryKeyMapping.copy;import java.io.Serializable;import javax.persistence.*;import org.hibernate.annotations.DynamicInsert;import org.hibernate.annotations.DynamicUpdate;import org.hibernate.annotations.SelectBeforeUpdate;@Entity//将POJO类转化成持久化类@Table(name="USER_INFO")//指定表名public class User{@Id@GeneratedValue(strategy=GenerationType.AUTO)private int id;private String name;private int age;private String address;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}}
生成的表user_info信息:


2.2 单个属性做主键: 在指定的属性上加@Id。

2.3 多个属性做联合主键。

  • 在多个属性上加@Id。
  • 这个持久化类必须实现Serializale接口。

例如:Person类的firstName和lastName两个属性要做联合主键,那么这两个属性上面都要加@Id注解,并且Person类要是实现Serializale接口。

Person实体类:

package edu.scut.b_PrimaryKeyMapping;import java.io.Serializable;import javax.persistence.*;@Entitypublic class Person implements Serializable {@Idprivate String firstName;@Idprivate String lastName;private int age;public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

2.4 复合属性做联合主键。

  • 在复合属性上加:@EmbeddedId。
  • 复合属性类必须实现Serializale接口。

例如:Employee实体类中,name属性是一个复合属性,要是以name属性作为主键,那么name属性上要加@Embedded注解,Name类要实现Serializale接口。

Employee类:

package edu.scut.b_PrimaryKeyMapping;import java.io.Serializable;import javax.persistence.*;@Entitypublic class Employee implements Serializable {@EmbeddedIdprivate Name name;public Name getName() {return name;}public void setName(Name name) {this.name = name;}private int age;public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

Name类:

package edu.scut.b_PrimaryKeyMapping;import java.io.Serializable;public class Name implements Serializable{private String firstName;private String lastName;public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}}


三、基本属性映射

3.1 @Column : 持久化类中属性转化成数据库表中列的相关信息。

  • name:指定列名。
  • length: 该列支持的长度。
  • precision:有效的总位数。(BigDecimal)。
  • scale:小数点的位数。(BigDecimal)。
  • unique: 唯一约束。
  • nullable:非空约束。
  • insertable:是否允许插入true:允许 false: 不允许。
  • updatable:是否允许修改true:允许 false: 不允许。
  • columnDefinition :指定列的定义。

例如:User类

package edu.scut.c_BasicFieldMapping;import java.io.Serializable;import java.math.BigDecimal;import javax.persistence.*;import org.hibernate.type.TrueFalseType;@Entity//将POJO类转化成持久化类@Table(name="USER_INFO")//指定表名public class User{@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="U_ID")private int id;@Column(name="U_NAME",//列名length=20, //长度nullable=false, //非空约束unique=false //唯一约束)private String name;@Column(name="U_AGE",columnDefinition="int(10) NOT NULL default 20")private int age;@Column(name="U_ADD",insertable=false, //允许插入updatable=false //允许修改)private String address;@Column(name="U_SALARY", precision=6, //小数的总位数scale=2)//小数点后面的位数 private BigDecimal salary;public int getId() { return id;}public BigDecimal getSalary() { return salary;} public void setSalary(BigDecimal salary) {this.salary = salary;} public void setId(int id) {this.id = id;}public String getName() { return name;} public void setName(String name) {this.name = name; }public int getAge() { return age;} public void setAge(int age) {this.age = age;}        public String getAddress() {return address; }public void setAddress(String address) {this.address = address; }}
生成的表user_info信息:


3.2 @Lob: 映射大的二进制数或者文本。

3.3 @Temporal:修饰日期类型Date。

  • TemporalType.DATE : yyyy-MM-dd。
  • TemporalType.TIME : HH:mm:ss。
  • TemporalType.TIMESTAMP : yyyy-MM-dd HH:mm:ss。

3.4  @Transient:指定不是持久化属性。

例如:Employee实体类

package edu.scut.c_BasicFieldMapping;import java.io.Serializable;import java.util.Date;import javax.persistence.*;@Entity@Table(name="EMP_INFO")public class Employee implements Serializable {@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="EMP_ID")private int id;@Column(name="EMP_NAME")private String name;@Column(name="EMP_PIC")@Lobprivate byte[] picture;@Column(name="EMP_BIRTH")@Temporal(TemporalType.TIMESTAMP)private Date birthday;@Transientprivate String remark; public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public byte[] getPicture() {return picture;}public void setPicture(byte[] picture) {this.picture = picture;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}}
生成的表emp_info信息:


四、复合属性映射

4.1 @Embedded:用于修饰复合属性(内含的)。

例如:Employee类中的name属性是复合属性,要用@Embedded注解修饰。

Employee实体类:

package edu.scut.d_MultiFieldMapping;import java.io.Serializable;import javax.persistence.*;@Entitypublic class Employee implements Serializable {@Id@GeneratedValue(strategy=GenerationType.AUTO)private int id;@Embedded //复合属性(将主键类的属性直接应用过来)private Name name;private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public Name getName() {return name;}public void setName(Name name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
Name实体类:

package edu.scut.d_MultiFieldMapping;import java.io.Serializable;import javax.persistence.Column;public class Name implements Serializable {private String firstName;private String lastName;public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}}
注意:复合属性的列名可以重命名,有两种方式。

4.2 @AttributeOverrides:第一种属性重新命名。在复合属性的上面加此注解。

@AttributeOverrides({@AttributeOverride(name="firstName", column=@Column(name="F_NAME")),     @AttributeOverride(name="lastName", column=@Column(name="L_NAME"))})
例如:Employee实体类

package edu.scut.d_MultiFieldMapping;import java.io.Serializable;import javax.persistence.*;@Entitypublic class Employee implements Serializable {@Id@GeneratedValue(strategy=GenerationType.AUTO)private int id;@Embedded //复合属性(将主键类的属性直接应用过来)        //改变复合属性的名称(第一种方式)@AttributeOverrides({@AttributeOverride(name="firstName",column=@Column(name="F_NAME")),     @AttributeOverride(name="lastName",column=@Column(name="L_NAME"))})private Name name;private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public Name getName() {return name;}public void setName(Name name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

4.3 第二种属性重命名方式:复合属性类的属性上面直接加@Column注解,给出列名。

例如:Name实体类

package edu.scut.d_MultiFieldMapping;import java.io.Serializable;import javax.persistence.Column;public class Name implements Serializable {@Column(name="F_NAME") //改变复合属性名称的第二种方式private String firstName;@Column(name="L_NAME")private String lastName;public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}}

五、继承映射

          当持久化类存在继承关系时,就可以用继承映射。继承映射提供了三种策略:

5.1 第一种方式(SINGLE_TABLE):所有子类中属性都生成到父类表中(一张表)。

             注意:所有子类属性中不能加非空约束。

5.1.1 父类

  • @Entity @Table(name="PER_INFO")。指定表名。
  • @Inheritance(strategy=InheritanceType.SINGLE_TABLE)。生成一张表。
  • @DiscriminatorColumn(name="DC", discriminatorType=DiscriminatorType.INTEGER) 。辨别者列,用来分辨每一行的信息对应的是哪个类的数据。
  • @DiscriminatorValue("1") 。辨别者列值,即每一个类的辨别者的不同代号。

父类:Person

package edu.scut.g_ExtendsMapping2;import javax.persistence.*;@Entity@Table(name="PER_INFO")@Inheritance(strategy=InheritanceType.SINGLE_TABLE) //只生成一张表@DiscriminatorColumn(name="DC",discriminatorType=DiscriminatorType.INTEGER) //辨别者列@DiscriminatorValue("1") //辨别者列的值public class Person {@Id@GeneratedValue(strategy=GenerationType.AUTO)private int id;private String name;private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

5.1.2 所有子类

  • @Entity。
  • @DiscriminatorValue("2")。指定辨别者列值。

子类:Employee

package edu.scut.g_ExtendsMapping2;import javax.persistence.*;@Entity@DiscriminatorValue("2")  //辨别者列的值public class Employee extends Person{private float salary;public float getSalary() {return salary;}public void setSalary(float salary) {this.salary = salary;}}
子类:Manager
package edu.scut.g_ExtendsMapping2;import javax.persistence.*;@Entity@DiscriminatorValue("3") //辨别者列public class Manager extends Employee{private String job;public String getJob() {return job;}public void setJob(String job) {this.job = job;}}

这三个类生成了一张表:

per_info表

5.2 第二种方式(JOINED):所有的子类与父类都会单独生成表(子类表的中主键列同时也是外键列,它引用顶级父类表中的主键列)。

              注意:查询时会出现很多join语句。

5.2.1 父类

  • @Entity @Table(name="PER_INFO")。
  • @Inheritance(strategy=InheritanceType.JOINED)。

父类:Person

package edu.scut.g_ExtendsMapping1;import javax.persistence.*;@Entity@Table(name="PER_INFO")@Inheritance(strategy=InheritanceType.JOINED) //会生成多张表,几个持久化类就生成几张表public class Person {@Id@GeneratedValue(strategy=GenerationType.AUTO)private int id;private String name;private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
5.2.2 子类

  •  @Entity @Table(name="")。

子类:Employee

package edu.scut.g_ExtendsMapping1;import javax.persistence.Entity;@Entitypublic class Employee extends Person{private float salary;public float getSalary() {return salary;}public void setSalary(float salary) {this.salary = salary;}}

子类:Manager

package edu.scut.g_ExtendsMapping1;import javax.persistence.Entity;@Entitypublic class Manager extends Employee{private String job;public String getJob() {return job;}public void setJob(String job) {this.job = job;}}
生成的三张表信息:

per_info表

employee表

manager表

5.3 第三种方式(TABLE_PER_CLASS):所有的子类与父类都会单独生成表,子类会把父类中的属性继承过来生成在自己的表中。

             注意:这种策略主键不能用自增长,查询时会出现union运算。

5.3.1 父类

  • @Entity @Table(name="PER_INFO")。
  • @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)。

父类:Person

package edu.scut.g_ExtendsMapping3;import javax.persistence.*;@Entity@Table(name="PER_INFO")@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)public class Person {@Id //@GeneratedValue(strategy=GenerationType.AUTO)  这种策略的ID不能自增长private int id;private String name;private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

5.3.2 子类

  • @Entity @Table(name="")

子类:Employee

package edu.scut.g_ExtendsMapping3;import javax.persistence.Entity;@Entitypublic class Employee extends Person{private float salary;public float getSalary() {return salary;}public void setSalary(float salary) {this.salary = salary;}}

子类:Manager

package edu.scut.g_ExtendsMapping3;import javax.persistence.Entity;@Entitypublic class Manager extends Employee{private String job;public String getJob() {return job;}public void setJob(String job) {this.job = job;}}
生成的三张表信息:

per_info表


employee表


manager表


                    













3 0
原创粉丝点击