一、Hibernate的开发步骤
注:导入的jar包:
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
jboss-logging-3.1.0.GA.jar
javassist-3.15.0-GA.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
hibernate-core-4.2.4.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
dom4j-1.6.1.jar
antlr-2.7.7.jar
hibernate-c3p0-4.2.4.Final.jar
c3p0-0.9.2.1.jar
mysql-connector-java-5.1.7-bin.jar
二、代码文件
1) hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 配置连接数据库的基本信息 -->
<property name="connection.username">root</property>
<property name="connection.password">1230</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///test</property>
<!-- 配置 hibernate 的基本信息 -->
<!-- hibernate 所使用的数据库方言 -->
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<!-- 执行操作时是否在控制台打印 SQL -->
<property name="show_sql">true</property>
<!-- 是否对 SQL 进行格式化 -->
<property name="format_sql">true</property>
<!-- 指定自动生成数据表的策略 -->
<property name="hbm2ddl.auto">update</property>
<!-- 指定关联的 .hbm.xml 文件 -->
<mapping resource="com/ithings/hibernate/helloworld/News.hbm.xml"/>
</session-factory>
</hibernate-configuration>
JDBC 连接属性
connection.url:数据库URLconnection.username:数据库用户名connection.password:数据库用户密码connection.driver_class:数据库JDBC驱动dialect:配置数据库的方言,根据底层的数据库不同产生不同的 sql 语句,Hibernate 会针对数据库的特性在访问时进行优化
C3P0 数据库连接池属性
hibernate.c3p0.max_size: 数据库连接池的最大连接数
hibernate.c3p0.min_size: 数据库连接池的最小连接数
hibernate.c3p0.timeout: 数据库连接池中连接对象在多长时间没有使用过后,就应该被销毁
hibernate.c3p0.max_statements: 缓存 Statement 对象的数量
hibernate.c3p0.idle_test_period: 表示连接池检测线程多长时间检测一次池内的所有链接对象是否超时. 连接池本身不会把自己从连接池中移除,而是专门有一个线程按照一定的时间间隔来做这件事,这个线程通过比较连接对象最后一次被使用时间和当前时间的时间差来和 timeout 做对比,进而决定是否销毁这个连接对象。
hibernate.c3p0.acquire_increment: 当数据库连接池中的连接耗尽时, 同一时刻获取多少个数据库连接
其他
show_sql:是否将运行期生成的SQL输出到日志以供调试。取值 true | false
format_sql:是否将 SQL 转化为格式良好的 SQL . 取值 true | false
hbm2ddl.auto:在启动和停止时自动地创建,更新或删除数据库模式。取值 create | update | create-drop | validate
hibernate.jdbc.fetch_size、hibernate.jdbc.batch_size
hibernate.jdbc.fetch_size:
实质是调用 Statement.setFetchSize() 方法设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数。
例如一次查询1万条记录,对于Oracle的JDBC驱动来说,是不会 1 次性把1万条取出来的,而只会取出 fetchSize 条数,当结果集遍历完了这些记录以后,再去数据库取 fetchSize 条数据。因此大大节省了无谓的内存消耗。Fetch Size设的越大,读数据库的次数越少,速度越快;Fetch Size越小,读数据库的次数越多,速度越慢。Oracle数据库的JDBC驱动默认的Fetch Size = 10,是一个保守的设定,根据测试,当Fetch Size=50时,性能会提升1倍之多,当 fetchSize=100,性能还能继续提升20%,Fetch Size继续增大,性能提升的就不显著了。并不是所有的数据库都支持Fetch Size特性,例如MySQL就不支持
hibernate.jdbc.batch_size:
设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,类似于设置缓冲区大小的意思。batchSize 越大,批量操作时向数据库发送sql的次数越少,速度就越快。
测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删除1万条记录需要25秒,Batch Size = 50的时候,删除仅仅需要5秒!Oracle数据库 batchSize=30 的时候比较合适。
2) 持久化类
package com.atguigu.hibernate.helloworld;
import java.sql.Blob;
import java.util.Date;
public class News {
private Integer id; //field
private String title;
private String author;
private String desc;
private String content;
private Blob picture;
public Blob getPicture() {
return picture;
}
public void setPicture(Blob picture) {
this.picture = picture;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
private Date date;
public Integer getId() { //property
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public News(String title, String author, Date date) {
super();
this.title = title;
this.author = author;
this.date = date;
}
public News() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "News [id=" + id + ", title=" + title + ", author=" + author
+ ", date=" + date + "]";
}
}
3) Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.atguigu.hibernate.helloworld">
<class name="News" table="NEWS" dynamic-insert="true">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<!-- 指定主键的生成方式, native: 使用数据库本地方式 -->
<generator class="native" />
</id>
<property name="title" not-null="true" unique="true"
index="news_index" length="50"
type="java.lang.String" column="TITLE" >
</property>
<property name="author" type="java.lang.String"
index="news_index">
<column name="AUTHOR" />
</property>
<property name="date" type="date">
<column name="DATE" />
</property>
<property name="desc"
formula="(SELECT concat(title, ',', author) FROM NEWS n WHERE n.id = id)"></property>
<property name="content">
<column name="CONTENT" sql-type="text"></column>
</property>
<property name="picture" column="PICTURE" type="blob"></property>
</class>
</hibernate-mapping>
Hibernate主键生成方式
1.assigned:
主键由外部程序负责生成,无需Hibernate参与。----如果要由程序代码来指定主键,就采有这种.
2.increment:
对 long , short 或 int 的数据列生成自动增长主键。increment主键生成方式的特点是与底层数据库无关性,大部分数据库如 Mysql,MSSQL 和ORACLE等都支持increament生成方式。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的 时候将此值加1作为主键。increment方式的不足之处是当多个线程并发对数据库表进行写操作时,可能出现相同的主键值,发生主键重复的冲突,因此多线程并发操作时,不应该使用此方法。
3.identity:
如果数据列的类型是 long, short 或 int ,可使用主键生成器生成自动增长Hibernate主键。与底层数据库有关,要求数据库支持identify,如MySQL中是auto_increment,SQL Server中是Identify.支持的数据库有MySQL,SQL Server,DB2,Sybase和HypersonicSQL.(好像不支持oracle) 无需Hibernate和用户的干涉,使用较为方便,但不便于在不同的数据库之间移植程序。identity的优点是不会发生 increment方式的并发错做问题。数据库涉及到的表要设置自动增长。
4.sequence:
在ORACLE等数据库中使用sequence生成主键。sequence的特点是于数据库的相关性,seqhio要求底层能支持sequence,列如Oracle。
5.hilo:
通过hi/lo 算法生成主键,需要一个表来保存额外的主键信息。这样生成的标识符只在特定的数据库是唯一的,在使用JTA(Java分布式事务) 获得链接或用户自定义提供的链接中,不要使用这种生成器。hilo方式需要维护表信息,因此对数据的影响的要率会造成一定影响。
6.seqhio:
与hilo 类似,通过hi/lo 算法实现的主键生成机制,只是主键历史状态保存在Sequence中,适用于支持Sequence的数据库,如Oracle。如果数据列的类型是 long, short 或 int可使用该主键生成器。
7.native:
由Hibernate根据不同的数据库方言,自行判断采用identity、hilo、sequence其中一种作为Hibernate主键生成方式,native的 优点是与底层性无关,便于不同数据库之间的移植,由Hibernate根据不同数据库选择主键的生成方式。在oracle中需要创建叫 Hibernate_sequence名字的sequence,如果设置了Hibernate.hbm2ddl.auto属性,不需要手动建立序列,前提 是数据库帐号必须有Create Sequence这种高级权限。mysql等数据库则不用建立sequence。
8.uuid.hex:
采用基于128位的算法生成唯一值,并编制成32位长度的唯一字符串作为主键值,uuid.hex的优点是支持大部分数据库,缺点就是要占用较大的存储空间。对于并发Insert要求较高的系统,推荐采用uuid.hex 作为主键生成机制。
9.uuid.string:
使用UUID算法,UUID被编码为一个16个字符长的任意ASCII字符组成的字符串。不能在PostgreSQL数据库中使用。uuid.string同uuid.hex类似,需要占很大的存储空间。
10.foreign:
使用外部表的字段作为Hibernate主键。
4) 通过Hibernate API编写访问数据库的代码
package com.ithings.hibernate.helloworld;
import java.sql.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.Test;
public class HibernateTest {
@Test
public void test() {
System.out.println("test...");
//1. 创建一个 SessionFactory 对象
SessionFactory sessionFactory = null;
//1). 创建 Configuration 对象: 对应 hibernate 的基本配置信息和 对象关系映射信息
Configuration configuration = new Configuration().configure();
//4.0 之前这样创建
// sessionFactory = configuration.buildSessionFactory();
//2). 创建一个 ServiceRegistry 对象: hibernate 4.x 新添加的对象
//hibernate 的任何配置和服务都需要在该对象中注册后才能有效.
ServiceRegistry serviceRegistry =
new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
//3).
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
//2. 创建一个 Session 对象
Session session = sessionFactory.openSession();
//3. 开启事务
Transaction transaction = session.beginTransaction();
//4. 执行保存操作
News news = new News("Java12345", "ATGUIGU", new Date(new java.util.Date().getTime()));
session.save(news);
//5. 提交事务
transaction.commit();
//6. 关闭 Session
session.close();
//7. 关闭 SessionFactory 对象
sessionFactory.close();
}
}
API详解
1)Configuration:
–Hibernate 运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml文件)。
–持久化类与数据表的映射关系(* . hbm.xml文件)
–属性文件(hibernate.properties):
•Configuration cfg= new Configuration();
–Xml文件(hibernate.cfg. xml)
• Configuration cfg = new Configuration().configure();
–Configuration 的configure方法还支持带参数的访问:
•File file= new File(“simpleit.xml”);
•Configuration cfg= new Configuration().configure(file);
2)SessionFactory接口
•针对单个数据库映射关系经过编译后的内存镜像,是线程安全的。
•SessionFactory对象一旦构造完毕,即被赋予特定的配置信息
•SessionFactory是生成Session的工厂
•构造SessionFactory很消耗资源,一般情况下一个应用中只初始化一个SessionFactory对象。
•Hibernate4新增了一个ServiceRegistry接口,所有基于Hibernate的配置或者服务都必须统一向这个ServiceRegistry 注册后才能生效
•Hibernate4中创建SessionFactory的步骤
3)Session接口
•Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate运作的中心,所有持久化对象必须在session的管理下才可以进行持久化操作。此对象的生命周期很短。Session对象有一个一级缓存,显式执行flush之前,所有的持久层操作的数据都缓存在session对象处。相当于JDBC中的Connection。
•持久化类与 Session关联起来后就具有了持久化的能力。
•Session 类的方法:
–取得持久化对象的方法: get()load()
–持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()
–开启事务: beginTransaction().
–管理 Session的方法:isOpen(),flush(),clear(), evict(), close()等
4)Transaction(事务)
•代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
Transactiontx= session.beginTransaction();
•常用方法:
–commit():提交相关联的session实例
–rollback():撤销事务操作
–wasCommitted():检查事务是否提交