Hibernate4学习总结
Posted TOMSCUT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate4学习总结相关的知识,希望对你有一定的参考价值。
Hibernate Annotation即hibernate注解,可以通过另一种方式将持久化类转化成表的相关信息,可以简化hibernate的配置文件。本文主要对Hibernate的注解进行讲解,由于篇幅原因,将注解部分分为两篇文章来写。集合映射和关联关系映射将在后面一文讲解。本文包括以下五个部分:
- 基础映射。
- 主键映射。
- 基本属性映射。
- 复合属性映射。
- 继承映射。
一、基础映射(注解加在持久化类上面)
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 { @Id 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.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.*; @Entity public class Person implements Serializable { @Id private String firstName; @Id private 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.*; @Entity public class Employee implements Serializable { @EmbeddedId private 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") @Lob private byte[] picture; @Column(name="EMP_BIRTH") @Temporal(TemporalType.TIMESTAMP) private Date birthday; @Transient private 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.*; @Entity public 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", [email protected](name="F_NAME")), @AttributeOverride(name="lastName", [email protected](name="L_NAME"))})例如:Employee实体类
package edu.scut.d_MultiFieldMapping; import java.io.Serializable; import javax.persistence.*; @Entity public class Employee implements Serializable { @Id @GeneratedValue(strategy=GenerationType.AUTO) private int id; @Embedded //复合属性(将主键类的属性直接应用过来) //改变复合属性的名称(第一种方式) @AttributeOverrides({@AttributeOverride(name="firstName",[email protected](name="F_NAME")), @AttributeOverride(name="lastName",[email protected](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; } }子类:Managerpackage 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; @Entity public class Employee extends Person{ private float salary; public float getSalary() { return salary; } public void setSalary(float salary) { this.salary = salary; } }
子类:Managerpackage edu.scut.g_ExtendsMapping1; import javax.persistence.Entity; @Entity public 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; @Entity 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_ExtendsMapping3; import javax.persistence.Entity; @Entity public class Manager extends Employee{ private String job; public String getJob() { return job; } public void setJob(String job) { this.job = job; } }生成的三张表信息:per_info表
employee表
manager表
以上是关于Hibernate4学习总结的主要内容,如果未能解决你的问题,请参考以下文章