0 回顾:
0.1 hibernate -> 操作数据库Dao
- 导包 - required/驱动包
- 准备数据库/实体类
配置文件
主配置文件
src/hibernate.cfg.xml
property:
project/etc/hibernate.properties
- 5[数据库连接信息+方言] + 3[
show
、format
、auto
] - 连接池
- mapping - 引入ORM元数据
- 5[数据库连接信息+方言] + 3[
ORM元数据配置 - 映射文件 - mapping
类、表的映射关系
<class name="" table> <id name column> <genertor class="native"> <property name>
使用
- 加载配置文件
Configuration configure()
- 获得
SessionFactory
- 获得
Session
- 开启事务
Transaction
session.get/load/save/delete/update
- 关闭事务
commit
/rollback
- 关闭资源
Session.close()
- 加载配置文件
一、JavaBean规范:
- 属性私有化,提供
get
/set
- 提供无参构造器
- 基本数据类型建议使用包装类
- 必须有主键oid对应属性
- 不能用
final
修饰 -> CGlib代理
二、主键
2.1 主键种类
代理主键:业务无关、对象无关,不能修改
自然主键:表中存在非空并且唯一的字段,例如身份证号
2.2 主键生成策略
- 主键生成策略 - 新增数据时,主键生成的方式
代理主键:
identity
:数据库维护,自增长,不需要手动录入sequence
:数据库维护,seq.nextVal
序列方式,需要指定参数[序列名],不需要手动录入increment
:Hibernate维护,自增长,不需要录入- 在插入之前先查找ID最大值,+1插入
hilo
:自增长算法
- 在插入之前先查找ID最大值,+1插入
native
:hilo
+identity
+sequence
- 自动检测
uuid
:hibernate维护,id类型设置为varchar(32)
自然主键:必须手动录入
assigned
三、Hibernate对象状态
3.1 瞬时状态
- 瞬时状态:对象没id,并且没有在
session
缓存中
3.2 持久化状态
持久化状态:对象有id,并且在
session
缓存中- 内容发生修改,在事务提交时,都会同步到数据库中
3.3 游离/托管状态
游离|托管状态:对象有id,没有不在
session
缓存中session
中对对象的操作,其实就是改变对象状态
四、session缓存与快照
4.1 session缓存
session
缓存作用:为了提高查询效率- hibernate一级缓存
@Test
public void test01() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 5.Session操作数据库 增删改查
// -----------------------
Customer c1 = session.get(Customer.class, 7l);
Customer c2 = session.get(Customer.class, 7l);
Customer c3 = session.get(Customer.class, 7l);
Customer c4 = session.get(Customer.class, 7l);
Customer c5 = session.get(Customer.class, 7l);
Customer c6 = session.get(Customer.class, 8l);
// Session 是有缓存的
System.out.println(c5 == c6);//true
// -----------------------
// 6.关闭事务
tx.commit();
// 7.关闭资源
session.close();
}
4.2 session快照
session
快照:为了节省不必要的update
操作- 懒加载:load方法懒加载,
lazy="true"
- 结论:默认设置,就是最佳优化方案
- 懒加载:load方法懒加载,
@Test
public void test02() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// -----------------------
Customer c = session.get(Customer.class, 7l);
c.setCust_name("阿里爸爸");
c.setCust_name("阿里爸爸1");
c.setCust_name("阿里爸爸2");
c.setCust_name("阿里爸爸3");
// 快照,节省不必要的操作,提高效率
c.setCust_name("阿里妈妈");
// -----------------------
// 6.关闭事务
tx.commit();
// 7.关闭资源
session.close();
}
Redis:缓存数据库,非关系型数据库
五、3种查询方式(重要)
5.1 HQL查询
HQL查询:Hibernate Query Language
- 永远不会出现和表相关信息
- 单表、简单的多表查询
session.createQuery(hql);
@Test
// 使用HQL查询全部Customer对象
public void test01() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// -----------------------
// 1> 通过hql获得query对象
// select * from cst_customer;
// from Customer
Query query = session.createQuery("from Customer");
// 2> 获得查询集合列表
List<Customer> list = query.list();
System.out.println(list);
// -----------------------
tx.commit();
session.close();
}
//-----------------------------------------------------------------------------------
@Test
// 使用HQL根据name查询Customer对象
public void test02() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// -----------------------
// 1> 通过hql获得query对象
// select * from cst_customer;
// from Customer where cust_name = ?
// Query query = session.createQuery("from Customer where cust_id = ? and cust_name=?");
//命名占位符
Query query = session.createQuery("from Customer where cust_id=:id and cust_name=:name");
// 2> 设置占位符参数
// query.setString(0, "阿里巴巴");
// query.setParameter(0, "阿里巴巴");
// :id :name - 命名占位符
query.setParameter("name", "阿里巴巴");
query.setParameter("id", 8l);
// 3> 获得结果集 - 唯一结果
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
// -----------------------
tx.commit();
session.close();
}
5.2 Criteria查询
Criteria查询:单表条件查询
- 只能做单表查询
session.createCriteria(Class);
@Test
// 使用Criteria查询全部Customer对象
public void test01() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// -----------------------
// 1> 通过session获得Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
// 2> 获得结果
List<Customer> list = criteria.list();
System.out.println(list);
// -----------------------
tx.commit();
session.close();
}
//-----------------------------------------------------------------------------------
@Test
// 使用Criteria根据name查询Customer对象
public void test02() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// -----------------------
// 1> 获得criteira对象
Criteria criteria = session.createCriteria(Customer.class);
// 2> 设置查询条件 - 静态方法Restrictions
criteria.add(Restrictions.eq("cust_name", "阿里巴巴"))
.add(Restrictions.idEq(8l));
// 3> 获得结果集 - 唯一结果
Customer customer = (Customer) criteria.uniqueResult();
System.out.println(customer);
// -----------------------
tx.commit();
session.close();
}
5.3 SQL查询
SQL查询
session.createSQLQuery(sql);
[Ljava.lang.Object;@2416a51
,未addEntity()
,输出的是这个,不是封装对象
addEntity();
-> 才能封装对象list()
-> 集合uniqueResult()
-> 单条记录
@Test
// 使用SQL查询全部Customer对象
public void test01() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// -----------------------
// 0> sql语句
String sql = "select * from cst_customer";
// 1> 通过session获得SQLQuery对象
SQLQuery sqlQuery = session.createSQLQuery(sql);
// 2> 获得结果 - 所有的记录,每一条封装为一个数组
List<Object[]> list = sqlQuery.list();
for (Object[] os:list) {
System.out.println(Arrays.toString(os));
}
// -----------------------
tx.commit();
session.close();
}
//----------------------------------------------------------------------------------
@Test
// 使用SQL查询全部Customer对象 - 封装对象
public void test03() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// -----------------------
// 0> sql语句
String sql = "select * from cst_customer";
// 1> 通过session获得SQLQuery对象
SQLQuery sqlQuery = session.createSQLQuery(sql);
// 在查询之前,添加实体类型
sqlQuery.addEntity(Customer.class);
// 2> 获得结果 - 按照实体类型,封装对象
List<Customer> list = sqlQuery.list();
System.out.println(list);
// -----------------------
tx.commit();
session.close();
}
//----------------------------------------------------------------------------------
@Test
// 使用sql根据name查询Customer对象
public void test02() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// -----------------------
// 0> sql语句,占位符只能用?
String sql = "select * from cst_customer where cust_name=?";
// 1> 获得SQLQuery对象
SQLQuery sqlQuery = session.createSQLQuery(sql);
// 2> 设置查询条件 - 静态方法Restrictions
sqlQuery.setParameter(0, "阿里巴巴");
// 3> 获得结果集 - 唯一结果
Customer customer = (Customer) sqlQuery.uniqueResult();
System.out.println(customer);
// -----------------------
tx.commit();
session.close();
}
六、事务回顾
- 事务:业务层面上,不能分割的最小单位
6.1 特点
特点:
- 原子性
- 一致性
- 持久性
- 隔离性
6.2 并发问题
并发问题:
- 脏读:别人没提交的事务,被我读到了
- 幻读:我刚删完的数据,别人又读出来了,感觉出现幻觉了
- 不可重复读:第一次读的数据和第二次读的不一样
隔离级别:
- 读未提交。0001
- 读已提交。0010
- 可重复读。0100
- 串行化。1000
mysql默认级别 isolution:4
- hibernate可以设置隔离级别 - 主配置文件
<!-- 设置隔离级别 -->
<!-- #hibernate.connection.isolation 4 -->
<property name="hibernate.connection.isolation">4</property>
<!-- 配置session和当前线程绑定
"current_session_context_class" thread
-->
<property name="current_session_context_class">thread</property>
6.3 误区
- 隔离级别设置
- session无需关闭