一、入门案例
数据表:
CREATE DATABASE h_day01_db;
USE h_day01_db;
CREATE TABLE t_user(
uid INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
PASSWORD VARCHAR(30)
);
User:
/**
* @author: RookieWangZhiWei
* @date:2018-3-7 下午8:36:05
* @version :
*
*/
public class User {
private int uid;
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
}
User.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 = "one.User" table = "t_user">
<id name = "uid" column="uid">
<generator class = "native"></generator>
</id>
<property name="username" column="username"></property>
<property name="password" column="password"></property>
</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.username">root</property>
<property name = "hibernate.connection.password">1234</property>
<property name = "hibernate.connection.url">jdbc:mysql://localhost:3306/h_day01_db</property>
<property name = "show_sql">true</property>
<property name = "format_sql">true</property>
<!-- hbm2ddl.auto: 生成表结构的策略配置
update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构.
如果存在表结构,并且表结构与实体一致,那么不做修改
如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
-->
<property name = "hbm2ddl.auto">update</property>
<property name = "hibernate.connection.autocommit">true</property>
<!-- 数据库方言配置
org.hibernate.dialect.MySQLDialect (选择最短的)
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<mapping resource="one/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
User.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">
<!-- ORM元数据 表对象关系映射文件
package : 配置该配置文件中类所在的包. -->
<hibernate-mapping package="one" >
<!-- class: 配置实体与表的关系
name : 填写实体的完整类名
table: 与实体对应表的名称
dynamic-insert:动态插入 默认值是false
true=>如果字段值为null,不参与insert语句
dynamic-update:动态更新 默认值"false"
true=> 没改动过的属性,将不会生成到update语句中
-->
<class name="User" table="t_user" >
<!-- id: 配置实体与表中 id对应
name: user对象中标识主键的属性名称
column: 主键在表中的列名
length: 列的数据长度
unsaved-value(不常用): 指定主键为什么值时,当做null来处理.
access(强烈推荐不要用):field 那么在操作属性时,会直接操作对应的字段而不是get/set方法
-->
<id name="id" column="id" length="255" >
<!-- generator:主键生成策略
1.increment 数据库自己生成主键. 先从数据库中查询最大的ID值,将ID值加1作为新的主键
2.identity 依赖于数据的主键自增功能
3.sequence 序列,依赖于数据中的序列功能(Oracle).
4.hilo(纯了解,永远用不到) : Hibernate自己实现序列的算法,自己生成主键. (hilo算法 )
5.native 自动根据数据库判断,三选一. identity|sequence|hilo
6.uuid 生成32位的不重复随机字符串当做主键
7.assigned 自己指定主键值. 表的主键是自然主键时使用.
-->
<generator class="uuid"></generator>
</id>
<!-- property : 实体中属性与表中列的对应
name : 实体中属性名称
column : 表中列的名称
length : 数据长度
precision: 小数点后的精度
scale: 有效位数
insert(一般不用): 该属性是否加入insert语句.
update(一般不用): 该属性是否加入update语句.
not-null : 指定属性的约束是否使用 非空
unique : 指定属性的约束是否使用 唯一
-->
<!--
type: 表达该属性的类型
可以用三种方式指定属性
java类型 数据库类型指定 Hibernate类型指定
java.lang.String varchar string
-->
<property name="name" column="name" update="true" type="string" ></property>
<property name="password" column="password"></property>
<property name="sal" column="sal" precision="2" scale="3" ></property>
</class>
</hibernate-mapping>
二、 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)加载指定目录下的 xml文件
4.手动加载配置文件
// 手动加载指定的配置文件
config.addResource("com/itheima/a_hello/User.hbm.xml");
// 手动加载指定类,对应的映射文件 User--> User.hbm.xml
config.addClass(User.class);
三、 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
四、Session会话
save 保存
update更新
delete删除
get通过id查询,如果没有 null
load通过id查询,如果没有抛异常
createQuery("hql") 获得Query对象
createCriteria(Class)获得Criteria对象
五、对象状态与一级缓存
瞬时态,session没有缓存对象,数据库也没有对应记录。
OID特点:没有值
持久态:persistent,session缓存对象,数据库最终会有记录。(事务没有提交)
OID特点:有值
脱管态:detached,session没有缓存对象,数据库有记录。
OID特点:有值
1.瞬时态/临时态
l 获得:一般都只直接创建(new)
l 瞬时态 转换 持久态
一般操作:save方法、saveOrUpdate
l 瞬时态 转换 脱管态
一般操作:通过setId方法设置数据
2.持久态
l 获得:
查询操作:get、loat、createQuery、createCriteria 等 获得都是持久态【】
执行save之后持久态
执行update之后持久态
l 持久态 转换 瞬时态
官方规定执行delete() --民间:删除态
l 持久态 转换 脱管态
session没有记录
session.close () 关闭
session.clear() 清除所有
session.evict(obj) 清除指定的PO对象
3.脱管态/游离态
l 获得:
创建、并设置OID的
通过api获得
l 脱管态 转换 瞬时态
手动去除OID,设置成默认值
l 脱管态 转换 持久态
一般操作:update()、saveOrUpdate
一级缓存
又称session级别的缓存,当获得一次会话(session),hibernate在session中创建多个集合(map),用于存放操作对象(PO对象),为程序优化服务,如果之后需要相应的数据,hibernate有现存session缓存中获取,如果有就使用,没有再查询数据库,当session关闭时,一级缓存被销毁。
一级缓存快照
快照与一级缓存在一样的存放位置,对一级缓存数据进行备份,保证数据库的数据与一级缓存的数据必须一致,如果一级缓存修改了,在执行commit提交时,将自动刷新一级缓存,执行update语句,将一级缓存的数据更新到数据库。
refresh刷新
refresh保证一级缓存的数据与数据库中的数据保持一致,将执行select语句查询数据库,将一级缓存的数据覆盖掉,只要执行refresh都将执行select语句。
ps: 一级缓存一般在默认情况下(commit())刷新
PO对象操作
1.save & persist
save方法:瞬时态转换持久态,会初始化OID
1.执行save方法,会立即触发insert语句,从数据库获得逐渐的值(OID值)
2.执行save方法前,设置OID将被忽略
3. 如果执行查询,session缓存已处理,在执行save方法时,将执行insert
persist方法:不会立即初始化OID
persist方法不会立即得到Id,所以执行sql语句的时机要靠后
2.update
update:脱管态转换持久态,
如果OID在数据存放的,将执行update语句
如果OID不存在将抛出异常
3.saveOrUpdate
l 代理主键:(native)
判断是否有OID
如果没有OID,将执行insert语句
如果有OID,将执行update语句。
l 自然主键:(assigned)
先执行select语句,查询是否存放
如果不存在,将执行insert
如果存在,将执行update