1.使用Hibernate注解的步骤
1.添加jar包
Hibernate-annotations.jar
Hibernate-commons-annotations.jar
ejb3-persistence.jar
2.使用注解配置持久化类及对象关联关系
3.使用AnnotationConfiguration建立会话工厂
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
4.在Hibernate配置文件(hibernate.cfg.xml)中声明持久化类
<mapping class="持久化类完整限定名" />
2.配置持久化类的常用注解
@Entity 将一个类声明为一个持久化类
@Id 声明了持久化类的标识属性(相当于数据表的主键)
@GeneratedValue 定义标识属性值的生成策略
@Table 为持久化类映射指定表(table)。目录(catalog)和schema的名称。默认值:持久化类名,不带包名
@UniqueConstraint 定义表的唯一约束
@Lob 表示属性将被持久化为Blob或者Clob类型
@Column 将属性映射到列
@Transient 忽略这些字段和属性,不用持久化到数据库
@GeneratedValue 定义标识属性值的生成策略,JPA提供了4种标准用法
(1) AUTO:根据不同的数据库选择不同的策略
(2) TABLE:使用表保存id值
(3) INDENTITY:使用数据库自动生成主键
(4) SEQUENCE:使用序列创建主键
3.十三种策略(strategy属性的值)如下:
● native
对于orcale采用Sequence方式,对于MySQL和SQL Server采用identity(处境主键生成机制),native就是将主键的生成工作将由数据库完成,hibernate不管(很常用)
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "native")
● uuid
采用128位的uuid算法生成主键,uuid被编码为一个32位16进制数字的字符串。占用空间大(字符串类型)。
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "uuid")
● hilo
要在数据库中建立一张额外的表,默认表名为hibernate_unque_key,默认字段为integer类型,名称是next_hi(比较少用)。
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "hilo")
● assigned
在插入数据的时候主键由程序处理(很常用),这是<generator>元素没有指定时的默认生成策略。等同于JPA中的AUTO。
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "assigned")
● identity
使用SQL Server和MySQL的自增字段,这个方法不能放到Oracle中,Oracle不支持自增字段,要设定sequence(MySQL和SQL Server中很常用)。等同于JPA中的IDENTITY
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "identity")
● select
使用触发器生成主键(主要用于早期的数据库主键生成机制,少用)
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "select")
● sequence
调用谨慎数据库的序列来生成主键,要设定序列名,不然hibernate无法找到。
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "sequence", parameters = { @Parameter(name = "sequence", value = "seq_payablemoney") })
● seqhilo
通过hilo算法实现,但是主键历史保存在Sequence中,适用于支持Sequence的数据库,如Orcale(比较少用)。
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "seqhilo", parameters = { @Parameter(name = "max_lo", value = "5") })
● increnment
插入数据的时候hibernate会给主键添加一个自增的主键,但是一个hibernate实例就维护一个计数器,所以在多个实例运行的时候不能使用这个方法。
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "increnment")
● foreign
使用另一个相关的对象的主键。通常和@OneToOne联合起来使用。
例:@Id
@GeneratedValue(generator = "idGenerator")
@GenericGenerator(name = "idGenerator", strategy = "foreign", parameters = { @Parameter(name = "property", value = "info") })
Integer id;
@OneToOne
EmployeeInfo info;
● guid
采用数据库底层的guid算法机制,对应MySQL的uuid()函数,SQL Server的newid()函数,ORCALE的rawtohex(sys_guid())函数等。
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "guid")
● uuid.hex
参见uuid,建议用uuid替换。
● sequence-identity
sequence策略的扩展,采用立即检索策略来获取sequence值,需要JDBC3.0和JDK4以上(含1.4)版本。
例:@GeneratedValue(generator = "paymentableGenerator")
@GenericGenerator(name = "paymentableGenerator", strategy = "sequence-identity", parameters = { @Parameter(name = "sequence", value = "seq_payablemoney") })
8. @Transient
声明了非持久化属性,即数据库中没有相应的映射字段,是一个普通属性。
9. @Temporal
声明了日期类型。
TemporalType.DATE 日期,例:2011-04-12
TemporalType.TIME 时间,例:22:50:30
TemporalType.TIMESTAMP 日期和时间,例:2011-04-12 22:51:30
10. @Version
声明了对乐观锁定的支持
例:@Version
@Column(name="OPTLOCK")
public Integer getVersion() { ... }
上面这个例子中,version属性将映射到 OPTLOCK列,entity manager使用该字段来检测更新冲突(防止更新丢失,请参考last-commit-wins策略)。
根据EJB3规范,version列可以是numeric类型(推荐方式)也可以是timestamp类型。Hibernate支持任何自定义类型,只要该类型实现了UserVersionType。
eg:
Emp.java
import javax.persistence.*
@Entity
@Talble(name="Emp")
public class Emp implements jaca.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "seq_emp")
@SequenceGenerator(name = "seq_emp",sequenceName = "seq_emp_id",
allocationSize = 10,initialValue = 1)
private Short empNo;
@Column(name = "ename")
private String eName;
@Column(name = "hiredate")
private Date hiredate;
@Transient
private Dept dept;
@Transient
private String job;
@Transient
private Short mgr;
@Transient
private Double salary;
@Transient
private Double comm;
public Emp(){}
//省略getter()和setter方法
}
Hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<mapping class="cn.jbit.hibernatedemo.entity.Emp"/>
</session-factory>
</hibernate-configuration>
测试类代码:
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Transantion tx = session.beginTranaction();
Emp emp = new Emp();
emp.setEmpName("test1");
emp.setHiredate(new Date());
session.save();
tx.commit();
//注:
1.Emp类映射到Emp表,empNo为主键,主键采用序列生成,需在数据库中创建序列Sequence,
名为seq_emp_id 注解都放置在属性定义的上方
2.使用@GeneratedValue设置主键生成策略,strantegy = Generatipe.Sequence描述了主键生成策略为Sequence
generator = "seq_emp"指定了生成器为seq_emp;
3.使用@SequenceGenerator设置了序列生成器,name="seq_emp"定义了序列生成器的名称为seq_emp;sequenceName
="seq_emp_id"指定了序列Sequence的名称为seq_emp_id,数据库中需创建序列Sequence,名称为seq_emp_id
;initialValue = 1 设置了主键初始值,默认为0;allocationSize=1表示预分配多少个主键值,如设置为1
表示不预分配主键值,默认为50
4.使用@Column把empName属性映射到EMP表中的Ename列
使用@Column把hiredate属性映射到EMP表中的Hiredate列
使用@Transient把其他属性忽略,不持久化到数据库中
在Hibernate.cfg.xml中,使用mapping元素声明持久化类
3.注解配置对象关联关系
@OneToOne 建立持久化类之间的一对一关联关系
@OneToMany 建立持久化类之间的一对多关联关系
@ManyToOne 建立持久化类之间的多对一关联关系
@ManyToMany 建立持久化类之间的多对多关联关系
3.1 按主键查询员工,并使用@ManyToMany加载部门
eg:
Emp.java
import javax.persistence.*
@Entity
@Talble(name="Emp")
public class Emp implements jaca.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "seq_emp")
@SequenceGenerator(name = "seq_emp",sequenceName = "seq_emp_id",
allocationSize = 10,initialValue = 1)
private Short empNo;
@Column(name = "ename")
private String eName;
@Column(name = "hiredate")
private Date hiredate;
@ManyToOne 使用@ManyToOne配置了Emp和Dept类之间的多对一关联;使用JoinColumn
(name="deptNo")指定了维系关系的外键字段是EMP表中的DeptNo。Hibernate
Hibernate生成的SQL语句使用了左外连接关键字
@JoinColumn(name = "deptno")
private Dept dept;
public Emp(){}
//省略getter()和setter方法
}
Dept.java
@Entity
@Talble(name="Dept")
public class Dept implements java.io.Serializable{
@Id
private Integer deptNo;
@Column(name="dname")
private String deptName;
//省略getter和setter方法
public Dept(){}
}
Hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<mapping class="cn.jbit.hibernatedemo.entity.Emp"/>
<mapping class="cn.jbit.hibernatedemo.entity.Dept"/>
</session-factory>
</hibernate-configuration>
测试类代码:
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Transantion tx = session.beginTranaction();
Emp emp = (Emp)session.load(Emp.class,new Short("3"));
System.out.print(emp.getEmpName()+","+emp.getDept().getDeptName());
3.2 级联的配置,添加部门的同时添加员工
cascade属性指定级联操作
1.CascadeType.remove:连接删除
2.CascadeType.persist:persist()方法级联
3.CascadeType.merge:级联更新
4.CascadeType.refresh:级联刷新
5.CascadeType.all:包含所欲有级联操作
eg:
Emp.java
import javax.persistence.*
@Entity
@Talble(name="Emp")
public class Emp implements jaca.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "seq_emp")
@SequenceGenerator(name = "seq_emp",sequenceName = "seq_emp_id",
allocationSize = 10,initialValue = 1)
private Short empNo;
@Column(name = "ename")
private String eName;
@Column(name = "hiredate")
private Date hiredate;
@ManyToOne 使用@ManyToOne配置了Emp和Dept类之间的多对一关联;使用JoinColumn
(name="deptNo")指定了维系关系的外键字段是EMP表中的DeptNo。Hibernate
Hibernate生成的SQL语句使用了左外连接关键字
@JoinColumn(name = "deptno")
private Dept dept;
public Emp(){}
//省略getter()和setter方法
}
Dept.java
@Entity
@Talble(name="Dept")
public class Dept implements java.io.Serializable{
@Id
private Integer deptNo;
@Column(name="dname")
private String deptName;
@Transient
private String location;
@OneToMany(mappedBy="dept",cascade = {CascadeType.ALL})
private Set<Emp> emps = new HashSet<Emp>();
//省略getter和setter方法
public Dept(){}
}
Hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<mapping class="cn.jbit.hibernatedemo.entity.Emp"/>
<mapping class="cn.jbit.hibernatedemo.entity.Dept"/>
</session-factory>
</hibernate-configuration>
测试类代码:
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Transantion tx = session.beginTranaction();
Dept dept = new Dept(6,"产品部");
Emp emp = new Emp();
emp.setEmpName("villy");
emp.setHiredate(new Date());
dept.getEmps().add(emp);
emp.setDept(dept);
session.save(dept)'
tx.commit();
4.注解配置命名查询
Emp.java
@Entity
@Talble(name="Emp")
@NamedQuery(name="selectEmp",query="from Emp where empName like :ename")
public class Emp implements jaca.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "seq_emp")
@SequenceGenerator(name = "seq_emp",sequenceName = "seq_emp_id",
allocationSize = 10,initialValue = 1)
private Short empNo;
@Column(name = "ename")
private String eName;
@Column(name = "hiredate")
private Date hiredate;
@ManyToOne 使用@ManyToOne配置了Emp和Dept类之间的多对一关联;使用JoinColumn
(name="deptNo")指定了维系关系的外键字段是EMP表中的DeptNo。Hibernate
Hibernate生成的SQL语句使用了左外连接关键字
@JoinColumn(name = "deptno")
private Dept dept;
public Emp(){}
//省略getter()和setter方法
}
测试类代码:
List<Emp> list = session.getNameQuery("selectEmp").setString("ename","%r%").list();
for(Emp emp : list){
System.out.print(emp.getEmpName);
}