首页 > 代码库 > JAVAWEB开发之Hibernate详解(一)——Hibernate的框架概述、开发流程、CURD操作和核心配置与API以及Hibernate日志的使用

JAVAWEB开发之Hibernate详解(一)——Hibernate的框架概述、开发流程、CURD操作和核心配置与API以及Hibernate日志的使用

Hibernate框架概述

什么是Hibernate?

 框架:软件的半成品,完成部分代码的功能。
Hibernate:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思想来操作数据库。Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序中使用,也可以在Servlet/JSP的web应用程序中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。

为何要学习Hibernate?

Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的ORM实现,它很大程度的简化了dao层编码工作。
HIbernate使用Java的反射机制,而不是字节码增强程序类实现透明性。
Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系。
ORM:Object Relational Mapping 对象关系映射
 传统方式开发:
  •  持久层:
  •  编写SQL.执行SQL. String sql = “insert into 表 values (?,?,?...)”;
  •  开发语言Java:面向对象.
  •  数据库:MySQL(关系型的数据库.)
  •  将Java中的实体类与数据库的关系表建立一个映射.就可以操作Java中对象,从而操作数据库.
Hibernate就是一个持久层的ORM的框架。
常见的持久层框架:
  • Hibernate:最流行的ORM框架,通过对象—关系映射配置,可以完全脱离底层SQL。
  • JPA:Java Persistence API. JPA通过JDK5.0注解或XML描述对象关系表的映射关系。(只有接口规范)
  • MyBatis:本是Apache的一个开源项目iBatis,支持普通的SQL查询,存储过程和高级映射的优秀持久层框架。
  • Apache DBUtils 、Spring JDBCTemplate
企业开发两种架构:
SSH:Struts2+Spring+Hibernate
SSI:SpringMVC+Spring+Ibatis

Hibernate版本:

Hibernate3.x版本和Hibernate4.x
企业中常用的还是Hibernate3.x

Hibernate日志记录

日志: 程序开发中的一些信息
常用信息输出:System.out.println(" ");
这种方式不好,原因如下:
如果输出的内容比较多,项目已经开发完毕,不想使用输出,需要输出每个类,将输出的代码注释。
日志:Hibernate中使用slf4j技术
slf4j:SLF4J,即简单门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。
  • 用于整合其他日志系统(在企业中常用的日志记录:log4J)
  • 是具体的日志记录方案

Log4J技术

开发中的日志操作
  • 开发阶段的调试信息
  • 运行时的日志记录(日志代码占代码总量的4%)
if (someCondition) {   
   System.out.println("some information.");
}
Hibernate中使用Log4J的步骤:
(1)导入Log4J的jar包apache-log4j-1.2.16(在Hibernate中使用时还需要导入slf4J的jar包)
在Hibernate中使用时需要单独下载SLF4J的jar包
技术分享

(2)编写Property文件(log4J的配置信息)参考模板在如下位置
Hibernate_HOME/project/etc 示例中可以将log4j.properties文件拷贝出来进行修改放在项目中的classPath即src下
技术分享
(3)在程序中获得logger对象,通过下列方法输出日志信息
  • public void debug(Object message);
  • public void info(Object message);
  • public void warn(Object message);
  • public void error(Object message);
利用信息级别确保日志信息在内容上和反映问题的严重程度上,是非常重要的。
  • fatal:非常严重的错误,导致系统终止。期望这类信息能立即显示在状态控制台上。
  • error:即普通错误,其它运行期错误或不是预期条件。期望这类信息能立即显示在状态控制台上。
  • warn:警告,使用了不赞成使用的API、非常拙劣的使用API,几乎就是错误,其它运行时不合需要和不合预期的状态但还没必要称为错误。期望这类信息能立即显示在状态控制台上。
  • info:普通信息。运行时产生有意义的事件。期望这类事件能立即显示在状态控制台上。
  • debug:系统流程中的细节信息。期望这类信息仅被写入log文件中。
  • trace:堆栈信息。期望这类信息仅被写入log文件中。
(4)配置文件(log4j.properties)
Log4J有三个主要部件:记录器(Loggers)、输出源(Appenders)、布局(Layouts)
组件简介:
记录器(loggers):用来配置日志输出级别,使用哪些输出源
  * 格式:记录器=级别,输出源1,输出源2...   
    如  log4j.rootLogger=info,stdout  info是日志级别,stdout是输出源名称
  * log4j提供日志级别 由高到低:fatal(致命错误)、error(普通错误)、warn(警告)、debug(调试)、trace(堆栈)
  * log4j记录日志时只会记录 配置级别以及更高级别的信息
输出源(appenders):在log4j中可以定义多个输出源(控制台、日志文件、邮件、数据库)
  * log4j.appender.输出源名称=实现类
  * log4j.appender.stdout=org.apache.log4j.ConsoleAppender  :控制台进行输出
  * log4j.appender.file=org.apache.log4j.FileAppender  :向文件进行输出
布局(Layouts) :在日志中都记录哪些信息
  * log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  :自定义布局
  * log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n  :自定义布局格式

示例如下:
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern= %-4r [%t] %-5p %c %x - %m%n

配置时的注意事项:
注意1、log4j.properties被放置到ClassPath所指定的目录下。
注意2、log4j的日志记录的优先级分为FATAL、ERROR、WARN、INFO、DEBUG、TRACE或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。

Log4J提供的输出源:
  • org.apache.log4j.ConsoleAppender(控制台)
  • org.apache.log4j.FileAppender(文件)
  • org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
  • org.apache.log4j.RollingFileAppender(文件到达指定大小时产生一个新文件)
  • org.apache.log4j.WriterAppender(将日志信息以流方式发送到任何地方)
Log4J提供的layout:
  • org.apache.log4j.HTMLLayout(以HTML表格形式布局)
  • org.apache.log4j.PatternLayout(可以灵活的自己指定布局模式)
  • org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
  • org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
自定义布局的layout中的格式符:
%c:列出logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名称空间。假设当前logger的名字空间是"a.b.c"
  • %c  —> a.b.c
  • %c{2} —>b.c
  • %c{1} —>c
  • %20c(若名字空间长度小于20,则左边用空格填充)
  • %-20c(若名字空间小于20,则右边用空格填充)
  • %.30c(若名字空间长度超过30,截取多余字符)
  • %20.30c(若名字空间长度小于20,则左边用空格填充;若名字空间长度超过30,截取多余字符)
  • %-20.30c(若名字空间长度小于20,则右边用空格填充;若名字空间超过30,截取多余字符)
%C:列出调用logger的类的全名(包含包路径),假设当前类是"org.apache.xyz.SomeClass"
  • %C —>org.apache.xyz.SomeClass    %C{2}—>xyz.SomeClass
%d:显示日志记录时间,{<日期格式>}  使用ISO8601定义的日期格式
  • %d{yyyy/MM/dd HH:mm:ss,sss} —> 2005/10/12 22:23:30,117
  • %d{ABSOLUTE} —> 22:23:30,117
  • %d{DATE} —> 12 Oct 2005 22:23:30,117
  • %d{ISO8601} —> 2005-10-12 22:23:30,117
%F:显示调用logger的源文件名  %F —> MyClass.java
%l:输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数
  • %l —> MyClass.main(MyClass.java:129)
%L:显示调用logger的代码行   %L—> 129
%m:显示输出消息  %m —> This is a message for debug
%M:显示调用logger的方法名  %M —> main
%n:当前平台下的换行符 Windows平台下表示rn   UNIX平台下表示n
%p:显示该条日志的优先级  %p —> INFO
%r:显示从程序启动到记录该条日志已经过去的毫秒数  %r —> 1215
%t:输出产生该日志事件的线程名  %t —> MyClass
%x:按NDC(Nested Diagnostic Context,线程堆栈)  假设某程序调用顺序是MyApp调用com.foo.Bar
       %c %x - %m%n   —>   MyApp - Call com.foo.Bar.
            com.foo.Bar - Log in Bar
              MyApp - Return to MyApp.
%X:按MDC(Mapped  Diagnostic  Context,线程映射表)输出日志。通常用于多个客户端连接同一台服务器,方便服务器区分是哪个客户端访问留下的日志    %X{5}  —> (记录代号为5的客户端记录)
%%:显示一个百分号   %% —> %

在Tomcat6下配置log4j的步骤
首先需要准备的文件为:
1.log4j.jar , 下载地址 :
http://www.apache.org/dist/logging/log4j/1.2.15/apache-log4j-1.2.15.zip
2.log4j配置文件:log4j.properties
注意:日志级别不能太低,如果配置为debug的话,输出的日志信息太多,导致tomcat启动非常的慢。 

获得logger 范例代码
package org.javaresearch.log4j;
import org.apache.log4j.*;
public class TestLog4J {   
static Logger log = Logger.getLogger(TestLog4J.class.getName());  
 public static void main(String args[]) {	    // logging的各种方法	  
  log.debug("Start of main()");  
 }
}
关于Log4J比较全面的配置
#应用于文件
log4j.appender.FILE=org.apache.log4j.FileAppender 
log4j.appender.FILE.File=C:\file.log 
log4j.appender.FILE.Append=false 
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender.FILE.layout.ConversionPattern= [framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
#应用于控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 
log4j.appender.CONSOLE.Target=System.out 
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

示例代码如下:
log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{2}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change ‘info‘ to ‘debug‘ ###

log4j.rootLogger=info, stdout ,file
Log4JTest
package cn.test.log4j;

import org.apache.log4j.Logger;
import org.junit.Test;

/**
 * 日志记录的类:
 *
 */
public class Log4JTest {
	
	private Logger logger = Logger.getLogger(Log4JTest.class);
	
	@Test
	public void demo1(){
		logger.fatal("致命错误");
		logger.error("普通错误");
		logger.warn("警告信息");
		logger.info("普通信息");
		logger.debug("调试信息");
		logger.trace("堆栈信息");
	}
}
技术分享
输出到日志文件
技术分享

Hibernate快速入门

第一步:下载Hibernate3.x的开发包(3.6.10)

http://sourceforge.net/projects/hibernate/files/hibernate3/
技术分享
slf4j与其他日志框架的关系
技术分享


第二步:Hibernate框架目录结构

技术分享
目录说明如下:
documentation :Hibernate文档
lib                     :Hibernate开发的jar包
     * bytecode  :操作字节码的jar包
     * jpa            :Hibernate的实现JPA规范
     * optional    :Hibernate的可选jar包
     * required   :Hibernate必须导入的jar包
project             :Hibernate提供的工程

第三步:创建一个工程:(Java工程)

导入相应的jar包:
*  hibernate3.jar
*  HIBERNATE_HOME / lib / required/*.jar
*  HIBERNATE_HOME/lib/jpa/hibernate-jpa-2.0-api-1.0.1.Final.jar
* 导入日志记录的包:
* log4j-1.2.16.jar
* slf4j-log4j12-1.7.2.jar
* 导入数据库驱动:

第四步:搭建环境(创建一个customer表与对应的持久化类)

技术分享技术分享

第五步:在Customer.class所在的目录创建映射文件

Customer.hbm.xml(类名.hbm.xml)
配置规则参考 hibernate2.jar org/hibernate/hibernate-mappong-3.0.dtd
查找位置如下:
技术分享
配置Customer.hbm.xml内容如下:
技术分享
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<!-- 配置类 和数据表 对应关系 -->
	<class name="cn.itcast.domain.Customer" table="customer" select-before-update="true">
		 <!-- 配置哪个属性 关联数据表主键 -->
		 <id name="id" column="id" type="integer">
		 	<!-- 主键生成策略 -->
		 	<generator class="identity"></generator>
		 </id>
		 <!-- 普通属性 -->
		 <property name="name" column="name" type="string"></property>
		 <!-- 如果属性名和列名相同 可以省略 column -->
		 <property name="age" type="integer" ></property>
		 <!-- 类型也可以使用默认生成规则,省略type -->
		 <property name="city"></property>
		 <property name="info"></property>
	</class>
</hibernate-mapping>

java、hibernate、sql类型对应关系
技术分享

第六步:配置JDBC连接数据库基本属性

在src下创建hibernate.cfg.xml
规则参考hibernate3.jar  /org/hibernate/hibernate-configuration-3.0.dtd
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>
	<!-- 会话连接工厂,建立数据库连接需要SessionFactory -->
	<session-factory>
		<!-- JDBC连接基本参数 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///hibernatetest</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">123</property>
		<!-- 配置数据库方言,便于生成一些与数据库相关SQL方言 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
		<!-- 可以根据需要自动创建数据表 -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		<!-- 将SQL语句 输出到控制台 -->
		<property name="hibernate.show_sql">true</property>
		<property name="hibernate.format_sql">true</property>
		
		<!-- JavaEE6 使用BeanValidator校验,需要设置校验模式-->
<!-- 		<property name="javax.persistence.validation.mode">none</property> -->
		
		<mapping resource="cn/itcast/domain/Customer.hbm.xml"></mapping>
	</session-factory>
</hibernate-configuration>

第七步:编程操作hibernate框架

// 实例化配置对象,加载配置文件 hibernate.cfg.xml
Configuration configuration = new Configuration().configure();
// 创建会话连接工厂
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 创建会话
Session session = sessionFactory.openSession();
// 开启事务
Transaction transaction = session.beginTransaction();
.
..  这里可以编写hibernate操作代码逻辑
// 提交事务,释放资源
transaction.commit();
session.close();
sessionFactory.close();

Hibernate的CRUD操作

Hibernate操作一(插入数据)

插入数据 通过Session对象的save方法  Serializable save(Object  object)
技术分享

Hibernate操作二(修改数据)

修改数据  通过Session的update方法   void  update(Object object)
技术分享
注意—修改有两种方式
方式一:手动创建对象的方式如下所示:
Customer customer = new Customer();
customer.setId(2);
customer.setName("苍老师");
session.update(customer);
使用这种方式,如果手动创建的对象中 只对一部分属性赋值,那么剩余的属性将以默认值存入(不建议使用)
方式二:先查询再进行修改的方式(推荐使用)
Customer customer = (Customer) session.get(Customer.class, 1);
customer.setName("凤姐");
session.update(customer);

Hibernate常用操作三(删除数据)

删除数据  通过Session的delete方法   void  delete(Object  object)
技术分享
注意—删除记录也有两种方式
删除方式一:手动创建对象的方式
// 手动创建对象的方式
Customer customer = new Customer();
customer.setId(2);
session.delete(customer);
方式二:先查询再删除的方式
Customer customer = (Customer)session.get(Customer.class, 1);
session.delete(customer);
两种方式的区别:当只涉及到一个表时,没有明显的区别,但当涉及到多个有关系的表时就有区别了 手动创建对象的删除方式是不能配置级联删除的,而先查询再删除的方式是可以配置级联删除的

Hibernate常用操作四(根据主键查询数据)

根据主键查询  通过Session的get或load方法
  • Object    get(Class clazz,  Serializable  id)
  • Object  load(Class clazz,  Serializable  id )
技术分享
* Customer customer = (Customer)session.get(Customer.class ,1);
* Customer customer = (Customer)session.load(Customer.class,1);
get和load的区别(重点+面试题)
1、发送SQL的时机不同
*  load这个方法采用了一个技术叫lazy延迟加载(懒加载)只有真正使用这个对象的数据的时候才发送SQL(对象的数据不包括主键  也就是说只查询主键时是不会发送SQL的)
*  get方法是立即检索,当执行session.get()方法的时候,马上发送SQL语句进行查询。
2、返回的对象不同
*  load方法返回的是代理对象。
*  get方法返回的是真实的对象。
3、查询一个不存在的数据时抛出的异常不同
*  load方法抛出异常:ObjectNotFoundException
*    get方法抛出异常:NullPointException

Hibernate常用操作五(查询所有数据)

 Hibernate框架查询数据  可以通过Query对象完成
Session对象提供了两个方法可以获得Query对象
  • Query  createQuery(String   queryString)  接受HQL
  • SQLQuery  createSQLQuery(String queryString)  接受SQL
HQL—Hibernate  Query Language  描写对象操作的一种查询语言
  • Query query=session.createQuery("from Customer");
  • 这里的Customer是类名
SQL—Structured Query Language  面向数据库查询语言
  • Query query = session.createSQLQuery("select * from customer");  
  • 这里参数就是普通SQL语句 
HQL查询结果会自动封装为Java对象
技术分享
SQLQuery会将查询结果每条数据封装为一个Object[]
技术分享
示例如下:
HQL:
HQL:Hibernate Query Language.
面向对象的写法:
Query query = session.createQuery("from Customer where name = ?");
query.setParameter(0, "苍老师");
query.list();
QBC:
Query By Criteria.(条件查询)
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.eq("name", "凤姐"));
List<Customer> list = criteria.list();
SQL:
SQLQuery query = session.createSQLQuery("select * from customer");
List<Object[]> list = query.list();
SQLQuery query = session.createSQLQuery("select * from customer");
query.addEntity(Customer.class);
List<Customer> list = query.list();

Hibernate运行的流程图如下:
技术分享

Hibernate常见配置及核心API

Hibernate体系结构及常见配置

技术分享
  • Hibernate的持久化方案,将用户从原始的JDBC底层SQL访问中解放出来。
  • 用户无须关注底层数据库的操作,只要通过操作映射到数据表的Java对象,就可以对数据库进行增删改查。
  • Hibernate框架支持哦两种Hibernate属性配置方式:hibernate.properties和hibernate.cfg.xml。
  • 采用properties方式必须手动编程加载hbm文件或者持久化类
  • 采用xml配置方式,可以配置添加hbm文件
   核心配置的两种方式进行配置:
         * 属性文件的配置:
                * hibernate.properties
                * 格式: key=value
                         * hibernate.connection.driver_class=com.mysql.jdbc.Driver
                ***** 注意:没有办法在核心配置文件中加载映射文件.(必须手动编码的方式进行加载.)
        * XML格式文件配置:
                * hibernate.cfg.xml
                * 格式:
                         <property name="hibernate.connection.username">root</property>

Hibernate核心配置常用属性

在project/etc/hibernate.properties中配置了hibernate常用的一些属性信息

核心配置中:

   1、必须的配置
         *连接数据库的4个基本参数:
               hibernate.connection.driver_class  连接数据库驱动程序
               hibernate.connection.url   连接数据库的URL
               hibernate.connection.username   数据库用户名
               hibernate.connection.password    数据库密码         
         *hibernate的方言
               hibernate.dialect   操作数据的方言

   2、可选的配置
          hibernate.show_sql   true   在控制台上输出SQL语句
          hibernate.format_sql   true  格式化控制台输出的SQL语句
          hibernate.connection.autocommit   true   事务是否自动提交
          hibernate.hbm2ddl.auto  create/create-drop/update/validate
          *  create  :每次执行的时候,创建一个新的表(如果以前有该表,将该表删除重新创建)一般测试的时候使用.
          *  create-drop:每次执行的时候,创建一个新的表,程序执行结束后将这个表删除掉了。一般测试的时候使用。
          *  update:如果数据库中没有表,创建一个新的表,如果有了,直接使用这个表。可以更新表的结构.
          *  validate:会使用原有的表,完成校验,校验映射文件与表中配置的字段是否一致,不一致报错
  3、映射的配置
         在核心配置文件中加载映射文件
             * <mapping resource="cn/itcast/hibernate3/demo1/Customer.hbm.xml" />
             * 使用手动编码的方式进行加载hbm.xml映射文件
                 configuration.addResource("cn/itcast/hibernate3/demo1/Customer.hbm.xml");
                 或 configuration.addClass(Customer.class);
          注意:在核心配置文件中加载映射文件时有一个小技巧

         技术分享    映射文件的配置

ORM:对象关系映射。需要在映射文件(命名格式:持久化类名.hbm.xml)中配置Java对象与表的映射。
*  配置类与表的映射:
         * name:类的全路径
         * table:表的名称(可以省略,若不写表名则使用类的名称作为表名)
          <class name="cn.itcast.hibernate3.demo1.Order" table=”orders”></class>
*  配置普通属性与字段映射:
         <property  name="name"  column="name"  type="string"  length="20" />
         type:三种写法
                *  Java类型:java.lang.String
                *  Hibernate类型:string
                *  SQL类型:不能直接使用type属性,需要子标签<column>
                         *  <column  name="name" sql-type="varchar(20)" />
*  配置唯一标识与主键映射:
         *  一个表中只有一个主键的形式
             <id name="id"  column="id">
                  <generator class="assigned"/>  <!-- 生成策略 -->
             </id>
         *  一个表对应多个主键形式:(复合主键)
             <composite-id>
                 <key-property name="firstname" column="firstname"  type="string" />
                          <key-property name="lastname" column="lastname"  type="string" />
             </composite-id>
*  关联关系
*  命名SQL
       <query  name="findAll">  from Customer  </query>
       <sql-query  name="sqlFindAll" >  select * from customer </sql-query>

Hibernate的核心API

Hibernate体系结构
技术分享

Hibernate  API简介 — Configuration类

Configuration类负责管理Hibernate的配置信息。包括如下内容:
  • 加载hibernate.propertieshibernate.cfg.xml
  • 持久化类与数据表的映射关系( *.hbm.xml)
1、加载核心配置文件 
      创建Configuration的两种方式
          方式一:加载属性文件(hibernate.properties
                Configuration  cfg = new Configuration();  // 手动加载hbm
          方式二:加载xml文件(hibernate.cfg.xml
                Configuration configuration = new Configuration().configure();
2、手动加载映射文件
      第一种写法:通过Configuration对象的addResource方法添加hbm文件映射
           //  加载位于cn.itcast.domain包下面Customer.hbm.xml文件
           configuration.addResource("cn/itcast/domain/Customer.hbm.xml");
      第二种写法:通过addClass添加持久化类,Hibernate会在类所在包自动搜索hbm映射文件
           要求:映射文件名称要规范,类与映射文件在同一个包下
          configuration.addClass(Customer.class);

Hibernate API简介—SessionFactory接口

Configuration对象根据当前的配置信息生成SessionFactory对象。
SessionFactory对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。
SessionFactory 对象是线程安全的。
SessionFactory还负责维护Hibernate的二级缓存。
  • Configuration configuration=new Configuration().configure();
  • SessionFactory sessionFactory = configuration.buildSessionFactory();
SessionFactory对象根据数据库信息,维护连接池,创建Session(相当于Connection)对象
  • Session  session = sessionFactory.openSession();
构造SessionFactory很消耗资源,一般情况下一个应用只初始化一个
抽取HibernateUtils类用来提供Session对象
技术分享
使用C3P0连接池
引入c3p0-0.9.1.jar
在hibernate.cfg.xml文件中增加如下配置:
<!-- C3P0连接池设定-->
<!-- 使用c3po连接池  配置连接池提供的供应商-->
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider </property>
<!--在连接池中可用的数据库连接的最少数目 -->
<property name="c3p0.min_size">5</property>
<!--在连接池中所有数据库连接的最大数目  -->
<property name="c3p0.max_size">20</property>
<!--设定数据库连接的过期时间,以秒为单位,
如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
<property name="c3p0.timeout">120</property>
 <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
<property name="c3p0.idle_test_period">3000</property>

Hibernate API简介—Session接口

相当于JDBC的Connection
Session是应用程序与数据库之间交互操作的一个单线程对象,是Hibernate运作的中心。
Session是线程不安全的。
所有持久化对象必须在session的管理下才可以进行持久化操作。
Session对象有一个一级缓存,显式执行flush之前,所有持久化操作的数据都缓存在session对象处。
持久化类与Session关联起来后就具有了持久化的能力。
Session维护了Hibernate的一级缓存。
常用方法如下:
save() / persist()   :添加。
update                  :修改。
saveOrUpdate      :增加和修改对象。
delete                    :删除对象。
get() / load()          :根据主键查询。
createQuery()       :创建一个Query接口,编写HQL语句。
createSQLQuery():创建一个SQLQuery接口,编写SQL语句  数据库操作对象。
createCriteria()     :返回一个Criteria接口,条件查询。

Hibernate API简介—Transaction接口

代表数据库操作的事务对象
  Transaction transaction = session.beginTransaction();
提供事务管理的方法:
  • commit():提交相关联的session实例。
  • rollback():撤销事务操作。
  • wasCommitted():检查事务是否提交。
如果没有开启事务,那么每个session的操作,都相当于一个独立的事务。注意:默认情况下这些独立的事务是不会提交的,都会进行回滚
思考题:关羽和张飞的信息能否插入数据库。
技术分享
如果在Hibernate的核心配置文件中配置了事务自动提交,则会将关羽的信息插入数据库,张飞的信息不会被插入数据库。如果在核心配置文件中没有配置事务自动提交,则张飞和关羽的信息都不会被插入数据库。

Hibernate API简介— Query接口

Query代表面向对象的一个Hibernate查询操作。
session.createQuery  接受一个HQL语句。
HQL是Hibernate  Query  Language缩写,语法很像SQL语法,但它是完全面向对象的。
使用Query对象的步骤:
  • 获得Hibernate  Session对象。
  • 编写HQL语句。
  • 调用session.createQuery 创建查询对象。
  • 如果HQL语句包含参数,则调用Query的setXXX设置参数。
  • 调用Query对象的list() 或uniqueResult() 方法执行查询。
Query还包含两个方法,用于控制返回结果。
  • setFirstResult(int  firstResult):设置返回结果从第几条开始
  • setMaxResults(int maxResults):设置本次返回结果的记录条数

HQL入门举例:

以from开始HQL语句,调用list方法返回 List<Customer>     
  • from Customer 查询customer表所有数据
使用select 关键字 (查询部分对象属性)
  • select name from Customer  返回List<String>
  • select name,age from Customer 返回 List<Object[] >
  • select c.name from Customer as c 为Customer实例起别名
使用where添加条件
from Customer as c where c.age > :age 其中:age是参数
技术分享
 from Customer as c where c.age > ? 其中?是参数
技术分享

Hibernate API简介—Criteria接口

Criteria是Hibernate提供的用于条件查询接口
Criteria criteria = session.createCriteria(Customer.class);
使用Criteria对象的步骤:
  • 获得Hibernate的Session对象
  • 通过Session获得Criteria对象
  • 通过Restrictions的静态方法创建Criterion条件对象
  • 向Criteria对象中添加Criterion查询条件
  • 执行Criteria的list() 或 uniqueResult() 获得结果
技术分享

Hibernate持久化配置和操作

Hibernate中的持久化类

Hibernate采用普通、传统的Java对象(POJO),作为持久化类,与数据表进行映射。
编写规则:
  • 提供一个无参数public访问控制符的构造器(无参构造函数,因为Hibernate要使用反射进行操作)
  • 提供一个标识属性,映射数据表主键字段。(Java区分两个对象是否是同一个使用地址,数据库区分两条记录是否一致使用主键,Hibernate中区分持久化对象是否是同一个则根据唯一标识)
  • 所有属性提供public访问控制符的set / get方法。(框架存取值的时候使用)
  • 标识属性应尽量使用基本数据类型的包装类型。
  • 不要使用final修饰(将无法生成代理对象进行优化)
注意:用final修饰的类是不能被继承的,无法生成代理对象(延迟加载的时候返回代理对象,延迟加载就会失效)

持久化对象的唯一标识OID

  • Java按地址区分同一个类的不同对象。
  • 关系数据库用主键区分同一条记录。
  • Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系。
  • 对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID进行赋值。

区分自然主键与代理主键

技术分享
技术分享
技术分享

持久化类属性用基本类型还是包装类型?

基本数据类型和包装类型对应hibernate的映射类型相同。
<property  name="price" type="double"  column="PRICE"  />
基本类型可直接运算、无法表达null、数字类型的默认值是0.
包装类型默认值是null。当对于默认值有业务意义的时候需要使用包装类。
例如:Student类有一个int类型的scope属性,表示学生的考试分数.int类型的scope属性无法表达这样的业务需求:
   * 如果scope的属性为null,表示该学生的成绩是未知的,有可能得了100分,也有可能得了0分,只是暂时还不知道成绩
   * 如果scope属性为0,表示学生考试成绩为0分.
   * 在上面的情况中必须使用包装类型

详解对象—关系映射 hbm文件

技术分享

ID和generator属性说明

id:设定持久化类的OID和表的主键的映射。id标签有以下属性:
  • name:表示持久化类OID的属性名。
  • column:设置标识属性所映射的数据列的列名(主键字段的名称)。
  • unsaved-value:若设定了该属性,Hibernate会通过比较持久化类的OID和该属性值来区分当前持久化类的对象是否是临时对象,Hibernate3中几乎不再需要。
  • type:指定 Hibernate 映射类型. Hibernate 映射类型是 Java 类型与 SQL 类型的桥梁. 如果没有为某个属性显式设定映射类型, Hibernate 会运用反射机制先识别出持久化类的特定属性的 Java 类型, 然后自动使用与之对应的默认的 Hibernate 映射类型
  • Java 的基本数据类型和包装类型对应相同的 Hibernate 映射类型. 基本数据类型无法表达 null, 所以对于持久化类的 OID 推荐使用包装类型(integer,long,string等)
generator:设置持久化类指定标识符生成器。
  • class:指定使用标识符生成器全限定 类名或其缩写名。

主键生成策略

常用的几种标识符生成器以及相关描述如下:
increment :适用于代理主键。由Hibernate自动以递增的方式生成标识符,每次增量为1.
identity     :适合代理主键。由底层数据库生成标识符。条件是数据库支持自动增长数据类型。
sequence :适用于代理主键。Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列。
native       :适用于代理主键。根据底层数据库对自动生成标识符的能力来选择identity、sequence、hilo。
uuid          :适用于代理主键。Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。
assigned  :适用于自然主键。由Java程序员负责生成标识符。不能把setId()声明为private类型。尽量避免使用自然主键。
主键生成策略increment
increment标识符生成器
increment 标识符生成器由Hibernate以递增的方式为代理主键赋值。
技术分享
Hibernate会先读取NEWS表中的主键的最大值,而接下来向NEWS表中插入记录时,就在max(id)的基础之上递增,增量为1(带走+1
适用范围:
  • 由于increment生存标识符机制不依赖于底层数据库系统,因此它是适用于所有的数据库系统。
  • 适用于只有单个Hibernate应用进程访问同一个数据库的场合。因为会产生多线程问题,在集群下不要使用。
  • OID必须为long,int,或short类型,如果把OID定义为byte类型,在运行时就会抛出异常。
主键生成策略 identity
identity标识符生成器由底层数据库负责生成标识符,它要求底层数据库把主键定义为自动增长字段类型(加1带走)
技术分享
适用范围:
  • 由于identity生成标识符的机制依赖于底层数据库系统,因此要求底层数据库系统必须支持自动增长字段类型。支持自动增长字段类型的数据库包括:DB2,MySQL,MSSQLServer,Sybase等。
  • OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时也会抛出异常。
主键生成策略 sequence
sequence标识符生成器利用底层数据库提供的序列来生成标识符。
技术分享
Hibernate在持久化一个NEWS对象时,先从底层数据库的news_seq序列中获得一个唯一的标识号,再把它作为主键值。
适用范围:
  • 由于sequence生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列。支持序列的数据库包括DB2、Oracle等。
  • OID必须为long、int、或short类型,如果把OID定义为byte类型,在运行时也会抛出异常。
主键生成策略 native
native标识符生成器依赖底层数据库对自动生成标识符的支持能力,来选择identity,sequence或hilo标识符生成器
技术分享
适用范围:
  • 由于native能根据底层数据库系统的类型,自动选择合适的标识符生成器,因此很适合用于跨数据库平台开发。
  • OID必须为long、int、或short类型,如果把OID定义为byte类型,在运行时也会抛出异常。
主键生成策略 uuid
uuid 32位标识符生成器
技术分享

Hibernate会产生不重复的32位字符作为主键。
主键生成策略 assigned
assigned标识符生成器— 用于映射单个自然主键。
假如CUSTOMER表没有定义ID代理主键,而是以NAME字段作为主键,那么相应的,在Customer类中不必定义id属性,Customer类的OID为name属性,它的映射代码如下:
技术分享
映射复合主键
技术分享

具体代码示例演示Hibernate:
项目如下:
技术分享   技术分享

Customer
package cn.itcast.hibernate3.demo1;
/**
 * 实体类对象
 *
 */
public final class Customer {
	private Integer id;
	//private String id;
	private String name;
	private int age;

	public Integer getId() {
		return id;
	}
	public void setId(Integer 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;
	}
	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
	
}
HibernateTest1
package cn.itcast.hibernate3.demo1;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

/**
 * Hibernate入门案例的测试:
 *
 *
 */
public class HibernateTest1 {
	
	@Test
	// 查询所有记录:SQL
	public void demo7(){
		// 1.加载核心配置文件
		Configuration configuration = new Configuration().configure();
		// 2.构建Session工厂
		SessionFactory sessionFactory = configuration.buildSessionFactory();
		// 3.通过工厂创建Session
		Session session = sessionFactory.openSession();
		// 4.开启事务
		Transaction tx = session.beginTransaction();
		
		// 5.操作
		// 查询所有:SQL
		/*SQLQuery query = session.createSQLQuery("select * from customer");
		List<Object[]> list = query.list();
		
		for (Object[] objs : list) {
			System.out.println(Arrays.toString(objs));
		}*/
		SQLQuery query = session.createSQLQuery("select * from customer");
		query.addEntity(Customer.class);
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		
		// 6.事务提交
		tx.commit();
		// 7.释放资源
		session.close();
		sessionFactory.close();
		
	}
	
	@Test
	// 查询所有:QBC
	public void demo6(){
		// 1.加载核心配置文件
		Configuration configuration = new Configuration().configure();
		// 2.构建Session工厂
		SessionFactory sessionFactory = configuration.buildSessionFactory();
		// 3.通过工厂创建Session
		Session session = sessionFactory.openSession();
		// 4.开启事务
		Transaction tx = session.beginTransaction();
		
		// 5.操作:
		// 查询所有 :QBC.
		/*Criteria criteria = session.createCriteria(Customer.class);
		List<Customer> list = criteria.list();*/
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.add(Restrictions.eq("name", "凤姐"));
		List<Customer> list = criteria.list();
		
		for (Customer customer : list) {
			System.out.println(customer);
		}
		
		// 6.事务提交
		tx.commit();
		// 7.释放资源
		session.close();
		sessionFactory.close();
	}
	
	@Test
	// 查询所有:HQL.
	// HQL:Hibernate Query Language.Hibernate查询语言.面向对象的查询.
	public void demo5(){
		// 1.加载核心配置文件
		Configuration configuration = new Configuration().configure();
		// 手动编码加载映射文件:
		// configuration.addResource("cn/itcast/hibernate3/demo1/Customer.hbm.xml");
		// configuration.addClass(Customer.class);
		// 2.构建Session工厂
		SessionFactory sessionFactory = configuration.buildSessionFactory();
		// 3.通过工厂创建Session
		Session session = sessionFactory.openSession();
		// 4.开启事务
		Transaction tx = session.beginTransaction();	
		
		// 5.操作
		// 1.查询所有的客户
		/*Query query = session.createQuery("from Customer");
		List<Customer> list = query.list();*/
		// 2.按名称查询
		/*Query query = session.createQuery("from Customer where name = ?");
		query.setParameter(0, "苍老师");*/
		Query query = session.createQuery("from Customer where name = :aaa");
		query.setParameter("aaa", "苍老师");
		List<Customer> list = query.list();
		
		for (Customer customer : list) {
			System.out.println(customer);
		}
		
		// 6.事务提交
		tx.commit();
		// 7.释放资源
		session.close();
		sessionFactory.close();
	}
	
	@Test
	// 删除记录
	public void demo4(){
		// 1.加载核心配置文件
		Configuration configuration = new Configuration().configure();
		// 2.构建Session工厂
		SessionFactory sessionFactory = configuration.buildSessionFactory();
		// 3.通过工厂创建Session
		Session session = sessionFactory.openSession();
		// 4.开启事务
		Transaction tx = session.beginTransaction();	
		
		// 5.操作
		// 删除记录有两种方式:
		// 5.1手动创建对象的方式
		/*Customer customer = new Customer();
		customer.setId(2);
		
		session.delete(customer);*/
		
		// 5.2先查询在删除的方式
		Customer customer = (Customer)session.get(Customer.class, 1);
		session.delete(customer);
		
		// 6.事务提交
		tx.commit();
		// 7.释放资源
		session.close();
		sessionFactory.close();
	}
	
	@Test
	// 修改记录
	public void demo3(){
		// 1.加载核心配置文件
		Configuration configuration = new Configuration().configure();
		// 2.构建Session工厂
		SessionFactory sessionFactory = configuration.buildSessionFactory();
		// 3.通过工厂创建Session
		Session session = sessionFactory.openSession();
		// 4.开启事务
		Transaction tx = session.beginTransaction();	
		
		// 5.操作:
		// 修改记录:两种方式可以进行修改.
		// 5.1手动创建对象的方式
		/*Customer customer = new Customer();
		customer.setId(2);
		customer.setName("苍老师");
		
		session.update(customer);*/
		
		// 5.2先查询在修改的方式
		Customer customer = (Customer) session.get(Customer.class, 1);
		customer.setName("凤姐");
		
		session.update(customer);
		
		// 6.事务提交
		tx.commit();
		// 7.释放资源
		session.close();
		sessionFactory.close();
	}
	
	@Test
	// 按id进行查询
	// (*****面试题)get和load方法区别
	public void demo2(){
		// 1.加载核心配置文件
		Configuration configuration = new Configuration().configure();
		// 2.构建Session工厂
		SessionFactory sessionFactory = configuration.buildSessionFactory();
		// 3.通过工厂创建Session
		Session session = sessionFactory.openSession();
		// 4.开启事务
		Transaction tx = session.beginTransaction();
		// 5.操作
		// 根据id进行查询:
		// get方法进行查询
		Customer customer = (Customer) session.get(Customer.class, 100); // 马上发生一条SQL进行查询
		
		System.out.println(customer);
		
		// load方法进行查询
		//Customer customer = (Customer) session.load(Customer.class, 100); // 没有发送SQL
		
		//System.out.println(customer);// 发送SQL.
		
		// 6.事务提交
		tx.commit();
		// 7.释放资源
		session.close();
		sessionFactory.close();
		
	}
	
	@Test
	// 保存记录
	public void demo1(){
		// 1.Hiberante框架加载核心配置文件(有数据库连接信息)
		Configuration configuration = new Configuration().configure();
		// 2.创建一个SessionFactory.(获得Session--相当连接对象)
		SessionFactory sessionFactory = configuration.buildSessionFactory();
		// 3.获得Session对象.
		Session session = sessionFactory.openSession();
		// 4.默认的情况下,事务是不自动提交.
		Transaction tx = session.beginTransaction();
		// 5.业务逻辑操作
		
		// 向数据库中插入一条记录:
		Customer customer = new Customer();
		customer.setName("苍老师");
		customer.setAge(38);
		
		session.save(customer);
		
		// 6.事务提交
		tx.commit();
		// 7.释放资源
		session.close();
		sessionFactory.close();
	}
}
Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束 -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<hibernate-mapping>
	<!-- 建立类与表的映射 -->
	<!-- class标签:用于映射类与表的关系 name :类的全路径  table:表名称 -->
	<class name="cn.itcast.hibernate3.demo1.Customer" table="customer">
		<!-- 建立类中属性与表中的字段映射 -->
		<!-- 唯一标识 -->
		<!-- 使用id的标签 配置唯一属性 -->
		<!-- 在<id>标签中配置一个主键的生成策略. -->
		<id name="id" column="id">
			<generator class="assigned"/>
		</id>
		
		<!-- 普通属性 -->
		<!-- property标签:映射类中的普通属性 name:类中的属性名称, column:表中字段名称 -->
		<!-- 
			type:三种写法
				* Java类型		:java.lang.String
				* Hibernate类型	:string
				* SQL类型		:不能直接使用type属性,需要子标签<column>
					* <column name="name" sql-type="varchar(20)"/>
		 -->
		<property name="name" column="name" type="string" length="20"/>
		<property name="age" column="age"/>
		
		
	</class>
	

</hibernate-mapping>
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>
	<!-- 必须去配置的属性 -->
	<!-- 配置数据库连接的基本信息: -->
	<property name="hibernate.connection.driver_class">
		com.mysql.jdbc.Driver
	</property>
	<property name="hibernate.connection.url">
		jdbc:mysql:///hibernate3_day01
	</property>
	<property name="hibernate.connection.username">root</property>
	<property name="hibernate.connection.password">123</property>
	<!-- Hibernate的方言 -->
	<!-- 生成底层SQL不同的 -->
	<property name="hibernate.dialect">
		org.hibernate.dialect.MySQLDialect
	</property>

	<!-- 可选的属性 -->
	<!-- 显示SQL -->
	<property name="hibernate.show_sql">true</property>
	<!-- 格式化SQL -->
	<property name="hibernate.format_sql">true</property>
	
	<property name="hibernate.connection.autocommit">false</property>
	<!-- hbm:映射 to DDL: create drop alter -->
	<property name="hibernate.hbm2ddl.auto">update</property>

	<!-- C3P0连接池设定-->
	<!-- 使用c3po连接池  配置连接池提供的供应商-->
	<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider                                                                                                                                                     </property>
	
	<!--在连接池中可用的数据库连接的最少数目 -->
	<property name="c3p0.min_size">5</property>
	<!--在连接池中所有数据库连接的最大数目  -->
	<property name="c3p0.max_size">20</property>
	<!--设定数据库连接的过期时间,以秒为单位,
	如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
	<property name="c3p0.timeout">120</property>
	 <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
	<property name="c3p0.idle_test_period">3000</property>

	<!-- 通知Hibernate加载那些映射文件 -->
	<mapping resource="cn/itcast/hibernate3/demo1/Customer.hbm.xml" />

</session-factory>
</hibernate-configuration>
log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{2}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change ‘info‘ to ‘debug‘ ###

log4j.rootLogger=info, stdout ,file

HibernateUtils
package cn.itcast.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * Hibernate抽取工具类
 * 
 *
 */
public class HibernateUtils {
	private static Configuration configuration;
	private static SessionFactory sessionFactory;
	
	static{
		configuration = new Configuration().configure();
		sessionFactory = configuration.buildSessionFactory();
	}
	
	public static Session openSession(){
		return sessionFactory.openSession();
	}
	
	public static void main(String[] args) {
		openSession();
	}
}

HibernateTest2
package cn.itcast.hibernate3.demo1;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

import cn.itcast.utils.HibernateUtils;

/**
 * 抽取了Hibernate的工具类的使用
 *
 */
public class HibernateTest2 {
	@Test
	// 保存数据
	public void demo1(){
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		Customer customer = new Customer();
		customer.setName("芙蓉");
		customer.setAge(26);
		
		session.save(customer);
		
		tx.commit();
		session.close();
	}
	
	@Test
	// 保存或更新()
	public void demo2(){
		// 获得SEssion
		Session session = HibernateUtils.openSession();
		// 开启事务
		Transaction tx = session.beginTransaction();
		
		/*Customer customer = new Customer();
		customer.setName("冠希");
		customer.setAge(34);
		
		session.saveOrUpdate(customer);*/
		
		Customer customer = new Customer();
		customer.setName("冠希");
		customer.setAge(34);
		
		session.saveOrUpdate(customer);
		
		System.out.println(tx.wasCommitted());
		
		// 事务提交
		tx.commit();
		
		System.out.println(tx.wasCommitted());
		// session关闭
		session.close();
	}
	
	@Test
	// 保存数据
	public void demo3(){
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		Customer customer = new Customer();
		customer.setName("芙蓉");
		customer.setAge(26);
		
		Serializable id = session.save(customer);
		
		// session.get(Customer.class, id);
		
		session.update(customer);
		
		tx.commit();
		session.close();
	}
	
	@Test
	// 测试程序
	public void demo4(){
		Session session = HibernateUtils.openSession();
		
		Customer customer = new Customer();
		customer.setName("关羽");
		customer.setAge(26);
		
		session.save(customer);
		
		int d = 10 / 0;
		
		Customer customer2 = new Customer();
		customer2.setName("张飞");
		customer2.setAge(26);
		
		session.save(customer2);
		
		session.close();
	}
	
	@Test
	// HQL:
	public void demo5(){
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		// 1.简单查询
		// List<Customer> list = session.createQuery("from Customer").list();
		
		// 2.条件查询:
		// List<Customer> list = session.createQuery("from Customer where name = ?").setParameter(0, "芙蓉").list();
		
		// 3.分页查询:select * from customer limit a,b; a:从哪开始  b:每页显示记录数.
		Query query = session.createQuery("from Customer");
		query.setFirstResult(3);
		query.setMaxResults(3);
		
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		
		tx.commit();
		session.close();
	}
	
	@Test
	// QBC:
	public void demo6(){
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		// 1.简单查询
		//List<Customer> list = session.createCriteria(Customer.class).list();
		
		// 2.条件查询:
		/*Criteria criteria = session.createCriteria(Customer.class);
		criteria.add(Restrictions.eq("name","芙蓉"));
		List<Customer> list = criteria.list();*/
		
		// 3.分页查询:
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.setFirstResult(3);
		criteria.setMaxResults(3);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		
		tx.commit();
		session.close();
	}
	
	@Test
	// 演示错误:(注意:)
	public void demo7(){
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		Customer customer = (Customer) session.get(Customer.class, 10);
		
		Customer customer2 = new Customer();
		customer.setId(10);
		customer.setName("张飞");
		session.update(customer2);
		
		tx.commit();
		session.close();
	}
	
	@SuppressWarnings("unused")
	@Test
	// 演示持久化类为final情况
	public void demo8(){
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		Customer customer = (Customer) session.load(Customer.class, 10);
		
		tx.commit();
		session.close();
	}
}
HibernateTest3
package cn.itcast.hibernate3.demo1;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.utils.HibernateUtils;

/**
 * 主键生成策略
 *
 */
public class HibernateTest3 {
	
	@Test
	// 演示increment的问题:
	public void demo1(){
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		Customer customer = new Customer();
		customer.setName("芙蓉");
		customer.setAge(26);
		
		session.save(customer);
		
		tx.commit();
		session.close();
	}
	
	@Test
	// 演示increment的问题:
	public void demo2(){
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		Customer customer = new Customer();
		// customer.setId(100);
		customer.setName("凤姐");
		customer.setAge(26);
		
		session.save(customer);
		
		tx.commit();
		session.close();
	}
}
Log4JTest
package cn.itcast.log4j;

import org.apache.log4j.Logger;
import org.junit.Test;

/**
 * 日志记录的类:
 */
public class Log4JTest {
	
	private Logger logger = Logger.getLogger(Log4JTest.class);
	
	@Test
	public void demo1(){
		logger.fatal("致命错误");
		logger.error("普通错误");
		logger.warn("警告信息");
		logger.info("普通信息");
		logger.debug("调试信息");
		logger.trace("堆栈信息");
	}
}


JAVAWEB开发之Hibernate详解(一)——Hibernate的框架概述、开发流程、CURD操作和核心配置与API以及Hibernate日志的使用