Hibernate 基础解析(Configuration,SessionFactory,Session,Transaction,Query,Criteria)
1 框架体系结构
对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实
现面向对象编程语言里不同类型系统的数据之间的转换[1] 。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟
对象数据库”。
2 hibernate入门
2.1 ORM框架
对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实
现面向对象编程语言里不同类型系统的数据之间的转换[1] 。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟
对象数据库”。
Hibernate是一个数据持久化层的ORM框架.
Object:对象,java对象,此处特指JavaBean
Relational:关系,二维表,数据库中的表。
映射|映射元数据:对象中属性,与表的字段,存在对应关系。
2.2 什么是hibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,
是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,
Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
Hibernate是轻量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架
- ORM 就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作
Hibernate提供了对关系型数据库增删改成操作
2.3 主流的ORM框架
JPA Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系(只有接口规范)
Hibernate 最流行ORM框架,通过对象-关系映射配置,可以完全脱离底层SQL
MyBatis 本是apache的一个开源项目 iBatis,支持普通 SQL查询,存储过程和高级映射的优秀持久层框架
Apache DBUtils 、Spring JDBCTemplate
2.4 优点
Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作 session.save(User);
Hibernate使用java的反射机制
Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系
3 入门案例【掌握】
3.1 编写流程
l 1. 导入jar包
l 2. 创建数据库和表
l 3. 编写核心配置文件(hibernate.cfg.xml)--> 配置获得链接等参数
l 4. 编写映射文件 hibernate mapping(*.hbm.xml)
l 5 使用api测试
3.2 数据库和表
3.3 导入jar包
l 版本:3.6.10 --> hibernate 4 建议注解开发,hibernate 4 对 3 不兼容。
l 目录结构
l jar介绍
Hibernate3.jar
核心:
必须:\lib\required
jpa规范:lib\jpa
Mysql-connector-java-5.0.8-bin.jar
mysql驱动:
3.4 编写JavaBean + 映射文件
l 文件位置:javabean同包
l 文件名称:javabean同名
l 扩展名:*.hbm.xml
l 内容:
添加约束
hibernate3.jar 下 org.hibernate 下 的 hibernate-mapping-3.0.dtd
1 <!DOCTYPE hibernate-mapping PUBLIC 2 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 5 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 6 7 <hibernate-mapping> 8 9 <class name="com.itheima.a_hello.User" table="t_user"> 10 11 <!-- 主键 --> 12 13 <id name="uid"> 14 15 <!-- 固定值:主键生成策略 --> 16 17 <generator class="native"></generator> 18 19 </id> 20 21 <!-- 普通属性 --> 22 23 <property name="username"></property> 24 25 <property name="password"></property> 26 27 </class> 28 29 </hibernate-mapping>
3.5 编写核心配置文件
l 位置:类路径(classpath、src)-->WEB-INF/classes
l 名称:hibernate.cfg.xml
l 内容:
添加约束
1 <!DOCTYPE hibernate-configuration PUBLIC 2 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 5 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 6 7 <hibernate-configuration> 8 9 <!-- SessionFactory,相当于之前学习连接池配置 --> 10 11 <session-factory> 12 13 <!-- 1 基本4项 --> 14 15 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 16 17 <property name="hibernate.connection.url">jdbc:mysql:///h_day01_db</property> 18 19 <property name="hibernate.connection.username">root</property> 20 21 <property name="hibernate.connection.password">1234</property> 22 23 24 25 <!-- 添加映射文件 --> 26 27 <mapping resource="com/itheima/a_hello/User.hbm.xml"/> 28 29 </session-factory> 30 31 32 33 </hibernate-configuration>
3.6 测试
1 @Test 2 3 public void demo01(){ 4 5 User user = new User(); 6 7 user.setUsername("伟哥哥"); 8 9 user.setPassword("1234"); 10 11 12 13 14 15 //1 加载配置文件获得核心配置对象 16 17 Configuration config = new Configuration().configure(); 18 19 //2 获得工厂 SessionFactory,相当于连接池 20 21 SessionFactory factory = config.buildSessionFactory(); 22 23 //3获得会话session,相当于链接Connection 24 25 Session session = factory.openSession(); 26 27 //4 开启事务 28 29 Transaction transaction = session.beginTransaction(); 30 31 32 33 //操作 34 35 session.save(user); 36 37 38 39 //5 提交事务 | 回滚事务 40 41 transaction.commit(); 42 43 //6 释放资源--关闭session 44 45 session.close(); 46 47 //7 释放资源--关闭工厂factory 48 49 factory.close(); 50 51 }
3.7 注意事项
将映射文件添加到核心配置文件中 hbm.xml --> hibernate.cfg.xml
4 api详解【多练】
4.1 体系结构
PO:persistent object ,用于与数据库交互数据。--dao层 (JavaBean + hbm )
BO:Business object 业务数据对象。--service层
VO:Value Object 值对象。--web层
开发中:直接使用JavaBean 描述三个对象。
4.2 Configuration 配置对象
l hibernate 核心配置文件种类
hibernate.cfg.xml 通常使用xml配置文件,可以配置内容更丰富。
hibernate.properties 用于配置key/value 形式的内容,key不能重复的。配置有很多的局限性。一般不用。
参考文件:hibernate-distribution-3.6.10.Final\project\etc\ hibernate.properties
提供了核心配置文件常用的配置项,及选择参数。
1.提供构造 new Configuration() hibernate将自动加载 hibernate.properties文件
hibernate.properties文件必须存放在类路径(src)下
2.提供方法 configure() 将加载src下的hibernate.cfg.xml
3.扩展api(如果核心配置文件不符合默认加载规则)
configure(String path ) 加载指定目录下的 xml文件
configure(File file) 通过file加载指定的xml文件。
4.手动加载配置文件(User.hbm.xml)
(推荐在 hibernate.cfg.xml 文件中使用 <mapping resource="com/itheima/a_hello/User.hbm.xml"/> 加载配置文件)
手动加载指定的配置文件
config.addResource("com/ittest/a_Test/User.hbm.xml");
手动加载指定类,对应的映射文件 User--> User.hbm.xml
config.addClass(User.class);
l 常见异常:
开发中:将hbm.xml映射 配置 hibernate.cfg.xml
学习中:可以使用 addClass 或 addResource
4.3 SessionFactory工厂
l SessionFactory 相当于java web连接池,用于管理所有session
l 获得方式:config.buildSessionFactory();
l sessionFactory hibernate缓存配置信息 (数据库配置信息、映射文件,预定义HQL语句 等)
l SessionFactory线程安全,可以是成员变量,多个线程同时访问时,不会出现线程并发访问问题。
l 提供api:
打开一个新的会话 session
factory.openSession();
获得当前线程中绑定的会话session
factory.getCurrentSession();
hibernate支持,将创建的session绑定到本地线程中,底层使用ThreadLocal,在程序之间共享session。
1.必须在hibernate.cfg.xml 配置
<!-- 2 与本地线程绑定 --> <property name="hibernate.current_session_context_class">thread</property>
|
2.如果提交或回滚事务,底层将自动关闭session
4.4 Session 会话
l Session 相当于 JDBC的 Connection -- 会话
l 通过session操作PO对象 --增删改查
l session单线程,线程不安全,不能编写成成员变量。
l session api
l
save 保存
update 更新
delete 删除
get : 通过id查询,如果没有 null;(其一查询就立刻使用sql语句查询数据库,并返回对象)
load : 通过id查询,如果没有就会抛异常;(其查询的时候只是给程序反回了一个代理对象,当我们要使用这个对象的时候,
代理对象才会使用session发送sql语句到数据库进行查询,并初始化属性)
特点: 继承代理, 一次查询(有一个初始化标记变量)
优点: 使用延迟加载,提高了运行效率(对于不需要具体内容的查询时可以使用load )
createQuery("hql") : 获得Query对象(然后查询数据库所有数据)
Query query = session.createQuery("from com.itheima.a_hello.User");
List<User> list = query.list();
createCriteria(Class) : 获得Criteria对象(然后查询数据库所有数据)
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
CreateSQLQuery(“SQL”) : 获得SQLQuery对象(然后查询数据库中所有的数据,并指定封装对象)
SQLQuery query = session.createSQLQuery("select * from t_user");
query.addEntity(User.class); (指定封装对象)
List<User> list = query.list();
4.5 Transaction 事务
开启事务 beginTransaction() : 开启一个新的事物。
获得事务 getTransaction() : 获得一个绑定在此线程上的事物。
提交事务:commit()
回滚事务:rollback()
(事务关闭时,会自动把与当前线程关联的session关闭,并删除)
try{ //开启 //session操作 //提交 } catch(e){ //回滚 } 扩展:不需要手动的管理事务,之后所有的事务管理都交予spring。 |
4.6 Query对象
l hibernate执行hql语句
l hql语句:hibernate提供面向对象查询语句,使用对象(类)和属性进行查询。区分大小写。
l 获得 session.createQuery("hql")
l 方法:
list() 查询所有
uniqueResult() 获得一个结果。如果没有查询到返回null,如果查询多条则抛返回异常。
setFirstResult(int) 分页,开始索引数startIndex
setMaxResults(int) 分页,每页显示个数 pageSize
4.7 Criteria对象(了解)
l QBC(query by criteria),hibernate提供纯面向对象查询语言,提供直接使用PO对象进行操作。
l 获得方式:Criteria criteria = session.createCriteria(User.class);
l 条件
criteria.add(Restrictions.eq("username", "tom"));
Restrictions.gt(propertyName, value) 大于
Restrictions.ge(propertyName, value) 大于等于
Restrictions.lt(propertyName, value) 小于
Restrictions.le(propertyName, value) 小于等于
Restrictions.like(propertyName, value) 模糊查询,注意:模糊查询值需要使用 % _ 。
之后也要使用uniqueResult方法。(也可以直接使用lis方法查找全部)
4.8 工具类
1 s H3Utils { 2 3 4 5 // 会话工厂,整个程序只有一份。 6 7 private static SessionFactory factory; 8 9 10 11 static{ 12 13 //1 加载配置 14 15 Configuration config = new Configuration().configure(); 16 17 18 19 //2 获得工厂 20 21 factory = config.buildSessionFactory(); 22 23 //3 关闭虚拟机时,释放SessionFactory 24 25 Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 26 27 28 29 @Override 30 31 public void run() { 32 33 System.out.println("虚拟机关闭!释放资源"); 34 35 sf.close(); 36 37 } 38 39 })); 40 41 } 42 43 44 45 46 47 /** 48 49 * 获得一个新的session 50 51 * @return 52 53 */ 54 55 public static Session openSession(){ 56 57 return factory.openSession(); 58 59 } 60 61 62 63 /** 64 65 * 获得当前线程中绑定session 66 67 * * 注意:必须配置 68 69 * @return 70 71 */ 72 73 public static Session getCurrentSession(){ 74 75 return factory.getCurrentSession(); 76 77 } 78 79 80 81 }
5 核心配置文件详解
5.1 详细配置
<!-- SessionFactory,相当于之前学习连接池配置 --> <session-factory> <!-- 1 基本4项 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql:///h_day01_db</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">1234</property>
<!-- 2 与本地线程绑定 --> <property name="hibernate.current_session_context_class">thread</property>
<!-- 3 方言:为不同的数据库,不同的版本,生成sql语句(DQL查询语句)提供依据 * mysql 字符串 varchar * orcale 字符串 varchar2 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 4 sql语句 --> <!-- 显示sql语句 --> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property>
<!-- 5 自动创建表(了解) ,学习中使用,开发不使用的。 * 开发中DBA 先创建表,之后根据表生产 PO类 * 取值: update:【】 如果表不存在,将创建表。 如果表已经存在,通过hbm映射文件更新表(添加)。(映射文件必须是数据库对应) 表中的列可以多,不负责删除。 create :如果表存在,先删除,再创建。程序结束时,之前创建的表不删除。【】 create-drop:与create几乎一样。如果factory.close()执行,将在JVM关闭同时,将创建的表删除了。(测试) validate:校验 hbm映射文件 和 表的列是否对应,如果对应正常执行,如果不对应抛出异常。(测试) --> <property name="hibernate.hbm2ddl.auto">create</property>
<!-- 6 java web 6.0 存放一个问题 * BeanFactory 空指针异常 异常提示:org.hibernate.HibernateException: Unable to get the default Bean Validation factory * 解决方案:取消bean校验 --> <property name="javax.persistence.validation.mode">none</property>
<!-- 添加映射文件 <mapping >添加映射文件 resource 设置 xml配置文件 (addResource(xml)) class 配置类 (addClass(User.class)) 配置的是全限定类名 --> <mapping resource="com/itheima/a_hello/User.hbm.xml"/> </session-factory> |
6 Hibernate中持久化类
6.1 编写规则
- 提供一个无参数 public访问控制符的构造器
- 提供一个标识属性,映射数据表主键字段
- 所有属性提供public访问控制符的 set get 方法(javaBean)
- 标识属性应尽量使用基本数据类型的包装类型
- 不要用final修饰实体 (将无法生成代理对象进行优化)
6.2 持久化对象的唯一标识 OID
l Java按地址区分同一个类的不同对象.
l 关系数据库用主键区分同一条记录
l Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系
结论: 对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID付值
6.3 区分自然主键和代理主键
l 主键需要具备: 不为空/不能重复/不能改变
自然主键: 在业务中,某个属性符合主键的三个要求.那么该属性可以作为主键列.
代理主键: 在业务中,不存符合以上3个条件的属性,那么就增加一个没有意义的列.作为主键.
6.4 基本数据与包装类型
l 基本数据类型和包装类型对应hibernate的映射类型相同
l 基本类型无法表达null、数字类型的默认值为0。
l 包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类。
6.5 类型对应
Java数据类型 |
Hibernate数据类型 |
标准SQL数据类型 |
byte、java.lang.Byte |
byte |
TINYINT |
short、java.lang.Short |
short |
SMALLINT |
int、java.lang.Integer |
integer |
INGEGER |
long、java.lang.Long |
long |
BIGINT |
float、java.lang.Float |
float |
FLOAT |
double、java.lang.Double |
double |
DOUBLE |
java.math.BigDecimal |
big_decimal |
NUMERIC |
char、java.lang.Character |
character |
CHAR(1) |
boolean、java.lang.Boolean |
boolean |
BIT |
java.lang.String |
string |
VARCHAR |
boolean、java.lang.Boolean |
yes_no |
CHAR(1)('Y'或'N') |
boolean、java.lang.Boolean |
true_false |
CHAR(1)('Y'或'N') |
java.util.Date、java.sql.Date |
date |
DATE |
java.util.Date、java.sql.Time |
time |
TIME |
java.util.Date、java.sql.Timestamp |
timestamp |
TIMESTAMP |
java.util.Calendar |
calendar |
TIMESTAMP |
java.util.Calendar |
calendar_date |
DATE |
byte[] |
binary |
VARBINARY、BLOB |
java.lang.String |
text |
CLOB |
java.io.Serializable |
serializable |
VARBINARY、BLOB |
java.sql.Clob |
clob |
CLOB |
java.sql.Blob |
blob |
BLOB |
java.lang.Class |
class |
VARCHAR |
java.util.Locale |
locale |
VARCHAR |
java.util.TimeZone |
timezone |
VARCHAR |
java.util.Currency |
currency |
VARCHAR |
6.6 普通属性
<hibernate-mapping> package 用于配置PO类所在包 例如: package="com.itheima.d_hbm" <class> 配置 PO类 和 表 之间对应关系 name:PO类全限定类名 例如:name="com.itheima.d_hbm.Person" 如果配置 package,name的取值可以是简单类名 name="Person" table : 数据库对应的表名 dynamic-insert="false" 是否支持动态生成insert语句 dynamic-update="false" 是否支持动态生成update语句 如果设置true,hibernate底层将判断提供数据是否为null,如果为null,insert或update语句将没有此项。 普通字段 <property> name : PO类的属性 column : 表中的列名,默认name的值相同 type:表中列的类型。默认hibernate自己通过getter获得类型,一般情况不用设置 取值1: hibernate类型 string 字符串 integer 整形 取值2: java类型 (全限定类名) java.lang.String 字符串 取值3:数据库类型 varchar(长度) 字符串 int 整形 <property name="birthday"> <column name="birthday" sql-type="datetime"></column> </property> javabean 一般使用类型 java.util.Date jdbc规范提供3中 java类型 mysql类型 java.sql.Date date java.sql.time time java.sql.timestamp timestamp null datetime
以上三个类型都是java.util.Date子类
length : 列的长度。默认值:255 not-null : 是否为null unique : 是否唯一 access:设置映射使用PO类属性或字段 property : 使用PO类属性,必须提供setter、getter方法 field : 使用PO类字段,一般很少使用。 insert 生成insert语句时,是否使用当前字段。 update 生成update语句时,是否使用当前字段。 默认情况:hibernate生成insert或update语句,使用配置文件所有项 注意:配置文件如果使用关键字,列名必须使用重音符 |
6.7 主键
主键 <id>配置主键 name:属性名称 access="" 设置使用属性还是字段 column="" 表的列名 length="" 长度 type="" 类型 <generator> class属性用于设置主键生成策略 1.increment 由hibernate自己维护自动增长 底层通过先查询max值,再+1策略 不建议使用,存在线程并发问题 2.identity hibernate底层采用数据库本身自动增长列 例如:mysql auto_increment 3.sequence hibernate底层采用数据库序列 例如:oracle 提供序列 4.hilo
</generator> 5.native 根据底层数据库的能力选择 identity、sequence 或者 hilo 中的一个。【】 ##以上策略使用整形,long, short 或者 int 类型 6.uuid 采用字符串唯一值【】 ##以上策略 代理主键,有hibernate维护。 7.assigned 自然主键,由程序自己维护。【】 |