Hibernate4学习总结

Posted TOMSCUT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate4学习总结相关的知识,希望对你有一定的参考价值。

      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 {
	@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;
	}
}
子类: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;

@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_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学习总结的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate4学习总结

springmvc4+hibernate4分页查询功能

Python学习总结

线程学习知识点总结

hibernate4.0+版本和3.0+版本的区别总结

Hibernate4学习一