美文网首页
day35 hibernate深入

day35 hibernate深入

作者: 路人爱早茶 | 来源:发表于2017-11-10 18:50 被阅读0次
  • 有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 , 没有关联
    }
1.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

相关文章

网友评论

      本文标题:day35 hibernate深入

      本文链接:https://www.haomeiwen.com/subject/blxmmxtx.html