一、我们从三个角度理解一下Hibernate:
1、Hibernate是对JDBC进一步封装
原来没有使用Hiberante做持久层开发时,存在很多冗余,如:各种JDBC语句,connection的管理,所以出现了Hibernate把JDBC封装了一下,我们不用操作数据,直接操作它就行了。
2、从分层的角度来看
我们知道非常典型的三层架构:表示层,业务层,还有持久层。Hiberante也是持久层的框架,而且持久层的框架还有很多,比如:IBatis,Nhibernate,JDO,OJB,EJB等等。
3、Hibernate是开源的一个ORM(对象关系映射)框架。
ORM,即Object-Relational Mapping,它的作用就是在关系型数据库和对象之间做了一个映射。从对象(Object)映射到关系(Relation),再从关系映射到对象。这样,我们在操作数据库的时候,不需要再去和复杂SQL打交道,只要像操作对象一样操作它就可以了(把关系数据库的字段在内存中映射成对象的属性)。
二、Hibernate框架的组成架构图如下
从上图中,我们可以看出Hibernate六大核心接口,两个主要配置文件,以及他们直接的关系。Hibernate的所有内容都在这了。
1)Configuration接口:负责配置并启动Hibernate
2)SessionFactory接口:负责初始化Hibernate
3)Session接口:负责持久化对象的CRUD操作
4)Transaction接口:负责事务
5)Query接口和Criteria接口:负责执行各种数据库查询
注意:Configuration实例是一个启动期间的对象,一旦SessionFactory创建完成它就被丢弃了。
三、Hibernate的优/缺点:
1、优点:
1)更加对象化
以对象化的思维操作数据库,我们只需要操作对象就可以了,开发更加对象化。
2)移植性
因为Hibernate做了持久层的封装,你就不知道数据库,你写的所有的代码都具有可复用性。
3)Hibernate是一个没有侵入性的框架,没有侵入性的框架我们称为轻量级框架。
对比Struts的Action和ActionForm,都需要继承,离不开Struts。Hibernate不需要继承任何类,不需要实现任何接口。这样的对象叫POJO对象。
4)Hibernate代码测试方便。
5)提高效率,提高生产力。
2、缺点:
1)使用数据库特性的语句,将很难调优
2)对大批量数据更新存在问题
3)系统中存在大量的攻击查询功能
四、hibernate配置:
准备工作:下载hibernate,这里下的是4.3.11版本的;
1、添加jar包到工程中:
2、在src根目录下创建hibernate.cfg.xml文件编写数据库配置文件:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@172.16.130.35:1521:orcl</property>
<property name="connection.username">wtyy1</property>
<property name="connection.password">wtyy1</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="com/zt/domain/Student.hbm.xml"/>
</session-factory>
</hibernate-configuration>
注意这一句
<property name="hbm2ddl.auto">update</property>
这一句非常重要,如果数据表不存在会自动创建,并且如果后来改了实体类(当然也改了映射)的话,这时候不需要手动去修改数据库,系统会自动更改数据库。
3、实体类:
Student.java:
package com.zt.domain;
import java.io.Serializable;
public class Student implements Serializable {
private int id;
private String name;
private String sex;
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
在实体类同级目录下创建映射文件Student.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.zt.domain">
<class name="Student" table="TB_STUDENT">
<id name="id" column="ID" type="int">
<generator class="native"></generator>
</id>
<property name="name" column="NAME"></property>
<property name="sex" column="SEX"></property>
</class>
</hibernate-mapping>
4、编写Util类获得SessionFactory:
package com.zt.util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
sessionFactory = new Configuration()
.configure() // configures settings from hibernate.cfg.xml
.buildSessionFactory();
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
5、测试程序:
package com.zt.test;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.zt.domain.Student;
import com.zt.util.HibernateUtil;
public class StudentTest {
public static void main(String[] args) {
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction ts=session.getTransaction();
ts.begin();
Student student=new Student();
student.setId(3);//如果已设为自动增长序列,则手动指定的会被忽略
student.setName("李四");
student.setSex("男");
session.save(student);
ts.commit();
session.close();
}
}
注意:这两个xml配置文件包括util类的编写方法(即SessionFactory的获取)在下载的hibernate里面都可以找到,并且不同的hibernate版本可能会有差异。
五、hibernate使用注解发方式完成实体类和数据表的映射:前面使用的是xml配置的方式,显得比较麻烦,下面使用注解发方式完成同样的功能:
package com.zt.domain;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity
@Table(name="student")
@SequenceGenerator(name="seq_stu")//主键生成
public class Student implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO,generator="seq_stu")
private int id;
private String name;
private String sex;
private String birthday;
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
现在就可以把之前的Student.hbm.xml文件删掉,把hibernate.cfg.xml里面原来的映射配置
<mapping resource="com/zt/domain/Student.hbm.xml"/>
改成:
<mapping class="com.zt.domain.Student"/>
OK!
说明:(注解实际上是一个注释,用来标记对象(字段,type,方法),为特殊用途,给某些程序读取使用,target:标记目标,type field method。)
@Retention:状态持续的范围
@Entity,注册在类头上,将一个类声明为一个实体bean(即一个持久化POJO类) 。
@Table,注册在类头上,注解声明了该实体bean映射指定的表(table)。
@SequenceGenerator( name="SEQ_ID",sequenceName="my_sequence")
@Id用来标识主属性列,
标记主键生成策略
@GeneratedValue:@GeneratedValue(strategy=GenerationType.IDENTITY)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_ID")
@Column:标识列-属性,
@Transient用来注册不是数据库关联的属性
以上的@Id、@GeneratedValue、 @Column:可以写在属性也可写在属性对应的getter上。
@Transient注册在多余的属性上,在getter上时必须与以上的@Column等对应
@Column里面的属性
name="列名"
unique=false该列是否设置唯一 默认false
nullable 该列是否可为空 默认false
insertable :该列在生成的insert语句中的出现 默认 true
updatable :该列在生成的update语句中的出现 默认 true
length :长度 默认255
六、oracle特殊字段对应hibernate的注解:
1、CLOB类型:大数据文本,对应的pojo字段类型为String,同时需要有注解说明:
@Lob
@Basic(fetch = FetchType.EAGER)
@Column(columnDefinition = "CLOB")
如:
package com.iflytek.domain;
import java.io.Serializable;
import java.sql.Clob;
import javax.persistence.Basic;
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.Lob;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.stereotype.Component;
//通知公告
@Component
@Entity
@Table(name = "T_MZYW_TZGG")
@SequenceGenerator(name = "seq_tzgg", sequenceName = "seq_tzgg")
public class Notice implements Serializable{
private String id;
private String tzggbt;
private String tzggzw;
public void setId(String id) {
this.id = id;
}
public void setTzggbt(String tzggbt) {
this.tzggbt = tzggbt;
}
public void setTzggzw(String tzggzw) {
this.tzggzw = tzggzw;
}
@Id
@GeneratedValue(generator = "seq_tzgg")
@GenericGenerator(name = "seq_tzgg", strategy = "uuid")
public String getId() {
return this.id;
}
public String getTzggbt() {
return this.tzggbt;
}
@Lob
@Basic(fetch = FetchType.EAGER)
@Column(columnDefinition="CLOB")
public String getTzggzw() {
return this.tzggzw;
}
public String toString() {
return "id=" + id + "tzggbt=" + tzggbt + "tzggzw=" + tzggzw + "tzggzt=" + tzggzt + "fbsj=" + fbsj + "fbcsbm="
+ fbcsbm + "fbcsmc=" + fbcsmc + "yxbs=" + yxbs + "cjyhbm=" + cjyhbm + "cjyhmc=" + cjyhmc + "zhxgyhbm="
+ zhxgyhbm + "zhxgyhmc=" + zhxgyhmc;
}
}
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(columnDefinition = "BLOB")
如:
package com.iflytek.domain;
import java.math.BigDecimal;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.stereotype.Component;
@Component
@Entity
@Table(name="T_mzyw_sczy")
@SequenceGenerator(name="seq_sczy",sequenceName="seq_sczy")
public class Sczy{
private String id;
private String glbmc;
private String glbxxdm;
private String glywdm;
private String cclx;
private String ljlx;
private String ccqlj;
private String wjm;
private String wjlx;
private byte[] wjnr;
private BigDecimal wjdx;
private String scsj;
private String yxbs;
public void setId(String id){
this.id=id;
}
public void setGlbmc(String glbmc){
this.glbmc=glbmc;
}
public void setGlbxxdm(String glbxxdm){
this.glbxxdm=glbxxdm;
}
public void setGlywdm(String glywdm){
this.glywdm=glywdm;
}
public void setCclx(String cclx){
this.cclx=cclx;
}
public void setLjlx(String ljlx){
this.ljlx=ljlx;
}
public void setCcqlj(String ccqlj){
this.ccqlj=ccqlj;
}
public void setWjm(String wjm){
this.wjm=wjm;
}
public void setWjlx(String wjlx){
this.wjlx=wjlx;
}
public void setWjnr(byte[] wjnr){
this.wjnr=wjnr;
}
public void setWjdx(BigDecimal wjdx){
this.wjdx=wjdx;
}
public void setScsj(String scsj){
this.scsj=scsj;
}
public void setYxbs(String yxbs){
this.yxbs=yxbs;
}
@Id
@GeneratedValue(generator="seq_sczy")
@GenericGenerator(name="seq_sczy",strategy="uuid")
public String getId(){
return this.id;
}
public String getGlbmc(){
return this.glbmc;
}
public String getGlbxxdm(){
return this.glbxxdm;
}
public String getGlywdm(){
return this.glywdm;
}
public String getCclx(){
return this.cclx;
}
public String getLjlx(){
return this.ljlx;
}
public String getCcqlj(){
return this.ccqlj;
}
public String getWjm(){
return this.wjm;
}
public String getWjlx(){
return this.wjlx;
}
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(columnDefinition = "BLOB")
public byte[] getWjnr(){
return this.wjnr;
}
public BigDecimal getWjdx(){
return this.wjdx;
}
public String getScsj(){
return this.scsj;
}
public String getYxbs(){
return this.yxbs;
}
public String toString(){
return "id="+id+"glbmc="+glbmc+"glbxxdm="+glbxxdm+"glywdm="+glywdm+"cclx="+cclx+"ljlx="+ljlx+"ccqlj="+ccqlj+"wjm="+wjm+"wjlx="+wjlx+"wjnr="+wjnr+"wjdx="+wjdx+"scsj="+scsj+"yxbs="+yxbs;
}
}