- 有id对应的(在数据库)瞬时态对象是游离状态,没有id对应就算有id属性也是瞬时状态。
------------练习 - request跳转不需要加项目名称(会自动加?)
- response重定向需要加项目名称(不必须)因为内部跳转可能找不到,图片地址也如此
------------批量查询 - hql多表简单查询,criteria单表查询,原生sql多表复杂查
- 问号索引是从0开始的,而jdbc是从1开始
@Test
public void fun1(){
//1 获得session
Session session = HibernateUtils.openSession();
//2 控制事务
Transaction tx = session.beginTransaction();
//3执行操作
//-------------------------------------------
--------------基本查询 将sql封装到query中 Customer 如果唯一可只写类名,如果不唯一需要全路径名称;sql语句中是类名和属性名称不可以出现表名和字段名
//1> 书写HQL语句
String hql = " from Customer where cust_id = 1 "; // 查询所有Customer对象
//2> 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//3> 根据查询对象获得查询结果
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
------------------问号占位符从0开始.setLong选择对应属性也可以setParameter综合;
还可以String hql = " from Customer where cust_id = :cust_id "; :cust_id 以冒号为占位符后面名称随意和query.setParameter("cust_id", 1l);搭配
//1> 书写HQL语句
String hql = " from Customer where cust_id = ? "; // 查询所有Customer对象
//2> 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//设置参数
//query.setLong(0, 1l);
query.setParameter(0, 1l);
//3> 根据查询对象获得查询结果
Customer c = (Customer) query.uniqueResult();
------------------分页查询没有limit而是setFirstResult和setMaxResults设置初始和最大
String hql = " from Customer "; // 查询所有Customer对象
//2> 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//设置分页信息 limit ?,?
query.setFirstResult(1);
query.setMaxResults(1);
//-------------------------------------------
//4提交事务.关闭资源
tx.commit();
session.close();// 游离|托管 状态, 有id , 没有关联
}
-------------------------------------------Criteria查询,先创建Criteria 对象,之后以调用属性来完成sql的条件
-----------------------基本
//查询所有的Customer对象
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
System.out.println(list);
// Customer c = (Customer) criteria.uniqueResult();
-----------------------//条件查询
//HQL语句中,不可能出现任何数据库相关的信息的
// > gt
// >= ge
// < lt
// <= le
// == eq
// != ne
// in in
// between and between
// like like
// is not null isNotNull
// is null isNull
// or or
// and and
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//添加查询参数 => 查询cust_id为1的Customer对象
criteria.add(Restrictions.eq("cust_id", 1l));
//执行查询获得结果
Customer c = (Customer) criteria.uniqueResult();
System.out.println(c);
-----------------------分页查询
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//设置分页信息 limit ?,?
criteria.setFirstResult(1);
criteria.setMaxResults(2);
//执行查询
List<Customer> list = criteria.list();
System.out.println(list);
--------------------//查询总记录数
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//设置查询的聚合函数 => 总行数
criteria.setProjection(Projections.rowCount());
//执行查询
Long count = (Long) criteria.uniqueResult();
System.out.println(count);
----------------------------------原生sql
-------------------基本
String sql = "select * from cst_customer";
//2 创建sql查询对象
SQLQuery query = session.createSQLQuery(sql);
//3 调用方法查询结果
List<Object[]> list = query.list();
//query.uniqueResult();
for(Object[] objs : list){
System.out.println(Arrays.toString(objs));
}
或者
//指定将结果集封装到哪个对象中
query.addEntity(Customer.class);
//3 调用方法查询结果
List<Customer> list = query.list();
------------------条件查询
String sql = "select * from cst_customer where cust_id = ? ";
//2 创建sql查询对象
SQLQuery query = session.createSQLQuery(sql);
query.setParameter(0, 1l);
//指定将结果集封装到哪个对象中
query.addEntity(Customer.class);
//3 调用方法查询结果
List<Customer> list = query.list();
------------------问号占位符
String sql = "select * from cst_customer limit ?,? ";
//2 创建sql查询对象
SQLQuery query = session.createSQLQuery(sql);
query.setParameter(0, 0);
query.setParameter(1, 1);
//指定将结果集封装到哪个对象中
query.addEntity(Customer.class);
//3 调用方法查询结果
List<Customer> list = query.list();
------------事务
- 注意使用currentsession必须要在主配置恩建中自己配
-----原则
-业务开始之前打开事务,业务执行之后提交事务. 执行过程中出现异常.回滚事务.
-在dao层操作数据库需要用到session对象.在service控制事务也是使用-session对象完成. 确保dao层和service层使用的使用同一个session对象
-在hibernate中,确保使用同一个session的问题,hibernate已经帮我们解决了. 我们只需要调用sf.getCurrentSession()方法即可获得与当前线程绑定的session对象
- 注意1: 调用getCurrentSession方法必须配合主配置中的一段配置
- 注意2:通过getCurrentSession方法获得的session对象.当事务提交时,session会自动关闭.不要手动调用close关闭.(否则报错)
-------配置<!-- 指定session与当前线程绑定 -->
<property name="hibernate.current_session_context_class">thread</property>
---------service
public class customerServiceImpl implements CustomerService {
private CustomerDao customerDao=new CustomerDaoImpl();
@Override
public void save(Customer customer) {
Session sess = HibernateUtils.getCurrentSesson();
Transaction tx = sess.beginTransaction();
try {
customerDao.save(customer);
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}
tx.commit();
}
-------------dao
public void save(Customer customer) {
// 获得session
Session sess = HibernateUtils.getCurrentSesson();
// 保存对象
sess.save(customer);
}
- acid(原子性:最小单位要么全成功要么全失败;一致性:原子性衍生,总量不变;隔离性:提供隔离级别解决并发问题;持久性:保证提交后写在硬盘)
- 并发问题
脏读:读到未提交数据
不可重复读:两次读取数据不一致
幻|虚读
<!-- 引入orm元数据
路径书写: 填写src下的路径
-->
<!-- 指定hibernate操作数据库时的隔离级别
#hibernate.connection.isolation 1|2|4|8
0001 1 读未提交
0010 2 读已提交
0100 4 可重复读
1000 8 串行化
-->
<property name="hibernate.connection.isolation">4</property>
-------------一级缓存
- 所以持久化对象就是放在缓存中的对象
----new 对象是瞬时,setid变成游离,update放入session缓存中变成持久化,但是session中没有快照,所以在commit会存入数据库调用一次sql
@Test
//持久化状态对象其实就是放入session缓存中的对象
public void fun3(){
//1 获得session
Session session = HibernateUtils.openSession();
//2 控制事务
Transaction tx = session.beginTransaction();
//3执行操作
Customer c1 = new Customer();
c1.setCust_id(1l);//托管|游离
session.update(c1);//c1被放入session缓存了
Customer c2 = session.get(Customer.class, 1l);
//4提交事务.关闭资源
tx.commit();
session.close();// 游离|托管 状态, 有id , 没有关联
}
- 提高效率手段:缓存的快照
-
查询先看session缓存中有没有(以id为标志)有就直接返回,没有继续。查找好的对象在hibernate中会有两份,一份缓存,一分快照,修改对象属性提交事务之后会比对快照和缓存是否相同。
1.png
-------------生成策略(状态)
- save方法不是保存而是将瞬时状态改变成持久状态(关联session并且生成id)
- 为了同步数据而学习状态观念
//三种状态特点
//save方法: 其实不能理解成保存.理解成将瞬时状态转换成持久状态的方法
//主键自增 : 执行save方法时,为了将对象转换为持久化状态.必须生成id值.所以需要执行insert语句生成.
//increment: 执行save方法,为了生成id.会执行查询id最大值的sql语句.
public void fun2(){
//1 获得session
Session session = HibernateUtils.openSession();
//2 控制事务
Transaction tx = session.beginTransaction();
//3执行操作
Customer c = new Customer(); // 没有id, 没有与session关联 => 瞬时状态
c.setCust_name("联想"); // 瞬时状态
session.save(c); // 持久化状态, 有id,有关联
//4提交事务.关闭资源
tx.commit();
session.close();// 游离|托管 状态, 有id , 没有关联}
--------------------状态特点
@Test
//三种状态特点
// 持久化状态特点: 持久化状态对象的任何变化都会自动同步到数据库中.
public void fun3(){
//1 获得session
Session session = HibernateUtils.openSession();
//2 控制事务
Transaction tx = session.beginTransaction();
//3执行操作
Customer c = session.get(Customer.class, 1l);//持久化状态对象
c.setCust_name("微软公司");
//4提交事务.关闭资源
tx.commit();
session.close();// 游离|托管 状态, 有id , 没有关联
}
![](https://img.haomeiwen.com/i5109746/7519c738756fd385.png)
-------------创建表注意
-----线程安全问题
<id name="cust_id" >
<!-- generator:主键生成策略.就是每条记录录入时,主键的生成规则.(7个)
identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.
sequence: Oracle中的主键生成策略.
increment(了解): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值.
hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
native:hilo+sequence+identity 自动三选一策略.
uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.
-->
<generator class="increment"></generator>
</id>
-------------实体对象创建注意
- hibernate创建实体走的是反射new instance,默认是空参方法
- 属性仅仅指getset方法
- 尽量使用基本类型的包装类型(long-Long)包装类型可以有null表达,但是基本类型没有null,如果数据库为空实体对象是基本类型,关联就会报错
- 没有主键无法映射到hibernate
网友评论