作者: 永恒の_☆ 地址: http://blog.csdn.net/chenghui0317/article/details/8392980
一、介绍
在以前弄hibernate的时候,每创建一个数据库表都要在entity下 新建对应的*.hbm.xml 配置文件,当数据库表很多之后就会严重影响开发效率和维护成本,所以 就有了注解,原理在于 省去之前繁琐的配置文件,取代的是在实体类中加上以“@”开头的标记,命名为 注解,待会一一解释其中含义。
二、准备
jar 文件:
hibernate-core-3.3.2.GA.jar
ejb3-persistence-1.0.2.GA.jar
hibernate-annotations-3.4.0.GA.jar
hibernate-commons-annotations-3.1.0.GA.jar
javassist-3.11.0.GA.jar
(缺一不可)
三、实现
既然要使用注解,那么在entity 就不需要实体映射文件了,取而代之的是在实体类中加上很多标记,这些标记的使用效果和使用配置文件配置一样,因为在使用hibernate映射文件的时候是利用dom4j 解析的,同样使用注解的标记也是由程序去解析的,其具体效果会在程序中体现出来。常用的注解标记 如下:
@Entity 标记为一个实体类,
@Table 标记为该类与一个数据表绑定,哪个表,要在参数中体现出来,比如:@Table(name = "tb_film_info") ,相当于映射文件中的
<class name="FilmInfo" table="tb_film_info"></class>
@Id 标记为Id,一般在主键出用到
@SequenceGenerator 标记为序列,将改字段与数据库中的序列绑定,在这里指定序列值才行,如果不使用该标记绑定将使用hibernate默认的序列,相当于映射文件中的
<generator class="sequence"></generator>
@GeneratedValue 标记为指定主键的生成策略,相当于映射文件的<param name="sequence">seq_film_info</param>
@Column 标记为该字段与数据库字段绑定,如果不指定具体的字段值,将默认采用单词分割首字母大写的特点绑定,比如 字段是 fi_ticket_price 那么对应的属性值 应该是 fiTicketPrice ,相当于映射文件中的
<property name="fiTicketPrice" type="java.lang.Double">
<column name="fi_ticket_price" length="10" not-null="true">
</column></property>
@ManyToOne 标记为多对一的关联映射关系,需要指定映射的实体类即可,相当于映射文件的
<many-to-one name="filmType" class="FilmType" >
<column name="fi_film_type_id" not-null="true"></column>
</many-to-one>
@JoinColumn 标记为关联的外键,相当于映射文件的 <column name="fi_film_type_id" not-null="true"></column>
@OneToMany 标记为一对多的关联映射关系,需要指定映射的实体类的级联方式等等,相当于映射文件的 <!-- 一个电影类型可以有多个电影详情,所以他们之间存在一对多的关联关系 -->
<bag name="filmInfos" table="tb_film_info" cascade="all" inverse="true">
<!-- 指定关联的字段,让字段作外键去关联 -->
<key>
<column name="fi_film_type_id" not-null="false"></column>
</key>
<!-- 指定关联的对象 -->
<one-to-many class="FilmInfo"></one-to-many>
</bag>
可见使用注解非常方便,省去了大部分繁琐的配置,从而节省了开发时间,提高了开发项目的效率。下面展示下两个简单的用到注解的实体类的例子,代码如下:
package com.hibernate.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
/**
* 电影详情类
* @author Administrator
*
*/
@Entity //标记为 数据库表
@Table(name = "tb_film_info") // 指定该实体类映射的对应的数据库表名
public class FilmInfo implements Serializable{
private static final long serialVersionUID = 1L;
private Long fiId;
private String fiName;
private String fiActor;
private String fiDirector;
private Double fiTicketPrice;
private FilmType filmType;
@Id //主键id
@SequenceGenerator(name = "generator", sequenceName = "seq_film_info" ) //指定序列
@GeneratedValue(generator = "generator", strategy = GenerationType.SEQUENCE) //指定主键生成策略
@Column(name = "fi_id") //因为数据表中的结构都是以“_”分割,然后 hibernate默认识别方式没有以任何方式分割,所以每个列都要在getter()方法标记
public Long getFiId() {
return fiId;
}
public void setFiId(Long fiId) {
this.fiId = fiId;
}
@Column(name = "fi_name")
public String getFiName() {
return fiName;
}
public void setFiName(String fiName) {
this.fiName = fiName;
}
@Column(name = "fi_actor")
public String getFiActor() {
return fiActor;
}
public void setFiActor(String fiActor) {
this.fiActor = fiActor;
}
@Column(name = "fi_director")
public String getFiDirector() {
return fiDirector;
}
public void setFiDirector(String fiDirector) {
this.fiDirector = fiDirector;
}
@Column(name = "fi_ticket_price")
public Double getFiTicketPrice() {
return fiTicketPrice;
}
public void setFiTicketPrice(Double fiTicketPrice) {
this.fiTicketPrice = fiTicketPrice;
}
@ManyToOne(fetch = FetchType.LAZY) //多对一关联关系,采用@ManyToOne标记,指定下加载方式
@JoinColumn(name = "fi_film_type_id") //指定下 关联的外键
public FilmType getFilmType() {
return filmType;
}
public void setFilmType(FilmType filmType) {
this.filmType = filmType;
}
}
package com.hibernate.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
/**
* 电影类型类
* @author Administrator
*
*/
@Entity//标记为 数据库表
@Table(name = "tb_film_type")// 指定该实体类映射的对应的数据库表名
public class FilmType implements Serializable{
private static final long serialVersionUID = 1L;
private Long ftId;
private String ftName;
private List<FilmInfo> filmInfos = new ArrayList<FilmInfo>();
@Id
@SequenceGenerator(name = "generator", sequenceName = "seq_film_type")
@GeneratedValue(generator = "generator", strategy = GenerationType.SEQUENCE)
@Column(name = "ft_id")
public Long getFtId() {
return ftId;
}
public void setFtId(Long ftId) {
this.ftId = ftId;
}
@Column(name = "ft_name")
public String getFtName() {
return ftName;
}
public void setFtName(String ftName) {
this.ftName = ftName;
}
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) //一对多关联关系,指定级联方式
@JoinColumn(name = "fi_film_type_id") // 这里指定 tb_Film_info 表的主键id,和引用tb_film_type表的外键都可以。
public List<FilmInfo> getFilmInfos() {
return filmInfos;
}
public void setFilmInfos(List<FilmInfo> filmInfos) {
this.filmInfos = filmInfos;
}
}
基本就是这个样子,然后 以前使用映射文件配置的时候都要在hibernate.cfh.xml中 加上映射的配置,比如:
<mapping resource="com/hibernate/entity/FilmInfo.hbm.xml"/>
<mapping resource="com/hibernate/entity/FilmType.hbm.xml"/>
那么用到注解之后 就不需要了。
另外以前使用hibernate映射文件配置获得SessionFactory 的方式是Configuration 的实例,但是使用hibernate注解之后要使用AnnotationConfiguration 的实例,如下:
/**
* Hibernate Session Factory
* @author Administrator
*
*/
public class HibernateSessionFactory {
static Session session = null;
static SessionFactory sessionFactory = null;
private static Logger logger = Logger.getLogger(HibernateSessionFactory.class);
//第一次加载该类才会执行,仅仅一次
static{
/* 当使用的是entity.hbm.xml 映射文件时,就使用下面的方式读取配置文件
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
*/
/* 如果实体类使用的是注解完成的,就使用下面的方式完成读取配置信息*/
AnnotationConfiguration annotationConfiguration = new AnnotationConfiguration().configure();
sessionFactory = annotationConfiguration.buildSessionFactory();
}
/**
* 得到session对象的实例
* @return
*/
public static Session getSession(){
session = sessionFactory.openSession();
logger.info("get this session case.");
return session;
}
/**
* 释放所有资源,关闭session服务
*/
public static void closeAll(){
if(session!=null){
session.close();
}
if(sessionFactory!=null){
sessionFactory.close();
}
logger.info("close this session.");
}
}
接下来在Junit 测试环境中演示一下:
0、获取FileInfo 表中价格在100元以下的电影信息
@Test
public void test00() {
Session session = HibernateSessionFactory.getSession();
Query query = session.createQuery("select info from FilmInfo info where info.fiTicketPrice <= 100");
Iterator<FilmInfo> iterators = query.iterate();
while(iterators.hasNext()){
FilmInfo info = iterators.next();
System.out.println("电影名 : " + info.getFiName() +" 价格:," + info.getFiTicketPrice());
}
HibernateSessionFactory.closeAll();
}
在控制台显示的效果如下:
1、获取FileInfo 表中价格在100元以下的电影信息
@Test
public void test01() {
Session session = HibernateSessionFactory.getSession();
//获取id为4的电影信息,包括该电影的电影类型
FilmInfo filmInfo = (FilmInfo) session.get(FilmInfo.class, (long)4);
System.out.println("电影名:" + filmInfo.getFiName());
FilmType fileType = filmInfo.getFilmType();
System.out.println("类型:" + fileType.getFtName());
System.out.println(fileType.getFilmInfos().size());
HibernateSessionFactory.closeAll();
}
在控制台显示的效果如下:
2、获取id为4的电影类型,包该类型下的所有电影信息
@Test
public void test02() {
Session session = HibernateSessionFactory.getSession();
//获取id为4的电影类型,包该类型下的所有电影信息
FilmType filmType = (FilmType) session.get(FilmType.class, 4l);
System.out.println("类型:" + filmType.getFtName());
List<FilmInfo> filmInfos = filmType.getFilmInfos();
for (FilmInfo filmInfo : filmInfos) {
System.out.println("电影名:"+filmInfo.getFiName());
}
HibernateSessionFactory.closeAll();
}
在控制台显示的效果如下:
3、添加一个电影信息,然后添加一个电影分类,先保存分类 在保存 电影。这里需要手动去保存
@Test
public void test03() {
//添加一个电影信息,然后添加一个电影分类,先保存分类 在保存 电影
FilmInfo filmInfo = new FilmInfo();
filmInfo.setFiActor("actor");
filmInfo.setFiDirector("director");
filmInfo.setFiName("finame");
filmInfo.setFiTicketPrice((double) 100);
FilmType filmType = new FilmType();
filmType.setFtName("typeName");
filmInfo.setFilmType(filmType);
Session session = HibernateSessionFactory.getSession();
Transaction transaction = session.beginTransaction();
transaction.begin();
//先保存分类,然后保存分类下的信息
session.save(filmType);
session.save(filmInfo);
transaction.commit();
HibernateSessionFactory.closeAll();
}
在控制台显示的效果如下:
4、添加一个电影信息,然后添加一个电影分类,保存分类的同时 级联保存电影信息
@Test
public void test04() {
//保存分类的同时 级联保存电影信息
FilmInfo filmInfo = new FilmInfo();
filmInfo.setFiActor("actor");
filmInfo.setFiDirector("director");
filmInfo.setFiName("finame");
filmInfo.setFiTicketPrice((double) 100);
FilmType filmType = new FilmType();
filmType.setFtName("typeName");
filmInfo.setFilmType(filmType);
filmType.getFilmInfos().add(filmInfo);
Session session = HibernateSessionFactory.getSession();
Transaction transaction = session.beginTransaction();
transaction.begin();
//先保存分类,然后保存分类下的信息
session.save(filmType);
transaction.commit();
HibernateSessionFactory.closeAll();
}
在控制台显示的效果如下:
那么 注解的使用先介绍到这里,其他的实现方式 和以前是一样的。