• hibernate学习(2)


    1 实体类编写规则

    2 hibernate主键生成策略

    3实体类操作

    (1)crud操作

    (2)实体对象状态

    4 hibernate的一级缓存

    5 hibernate事务操作

    (1)事务代码规则写法

    6 hibernate其他的api(查询)

    实体类编写规则

    1 实体类里面属性私有的

    2 私有属性使用公开的set方法和get方法操作

    3 要求实体类有属性作为唯一值(一般都使用id值)

    4 实体类属性建议不使用基本数据类型,使用基本数据类型对应的包装类。

    (1)八个基本数据类型对应的包装类

    -int - Integer

    -char--Character

    -其他的都是首字母大写 比如double-Double

    (2)比如表示学生的分数,假如 int score;

    -比如学生得了0分,int score-0;

    -如果表示学生没有参加考试,int scrore无法为null,int score不能准确表示学生是否参加考试

    解决:使用包装类可以了,Integer score=0,学生得了0分

    表示学生没有参加考试,Integer score=null;

    Hibernate主键生成策略

    1 hibernate要求实体类里面有一个属性作为唯一值,对应主键,主键可以不同生成策略

    2 hibernate主键生成策略有很多的值

    <!-- 设置数据库id增长策略 native:生成表id值就是主键自动增长 -->
    <generator class="native"></generator>

     

    主要记住native和uuid。

    identity只能用在mysql中,sequence只能用在oracle中。

    因为不知道用什么数据库,所以用native,它会帮我们根据不同的数据库选择不一样的值。

    (1)native:根据使用的数据库帮我们选择哪个值

    CREATE TABLE `t_user` (
      `uid` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(255) DEFAULT NULL,
      `password` varchar(255) DEFAULT NULL,
      `address` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`uid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 |

     (2)uuid:hibernate帮我们生成uuid值。

    (1)使用uuid生成策略,实体类id属性类型必须是字符串类型。

     在User.java中

    private String uid;
    //如果有哪个属性值没有生成get和set方法,那么程序会出现异常
        

    在User.hbm.xml中

    <generator class="uuid">
    </generator>

    show create table t_user;展示如下所示:

    CREATE TABLE `t_user` (
      `uid` varchar(255) NOT NULL,
      `username` varchar(255) DEFAULT NULL,
      `password` varchar(255) DEFAULT NULL,
      `address` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`uid`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

    实体类操作

    对实体类crud操作

    添加操作

    1 调用session里面的save方法实现

    //添加功能
    User user = new User();
    user.setUsername("xiaoMA");
    user.setPassword("250");
    user.setAddress("China");
    session.save(user);

    根据id查询

     hibernate可以帮我们创建表,但无法创建数据库。

    1 调用session里面的get方法实现

    //4 根据id查询
    //调用session里面的get方法
    //第一个参数:实体类的class
    //第二个参数:id值
    User user = session.get(User.class, 1);

    底层输出语句

    <!-- 输出底层sql语句 -->
    <property name="hibernate.show_sql">true</property>

    的输出结果是:

    Hibernate: 
        select
            user0_.uid as uid1_0_0_,
            user0_.username as username2_0_0_,
            user0_.password as password3_0_0_,
            user0_.address as address4_0_0_ 
        from
            t_user user0_ 
        where
            user0_.uid=?
    User [uid=1, username=lucy, password=123, address=china]

    修改操作

    (1)根据id查询,返回对象

    // 4 修改操作
    // 修改uid=2记录username值
    User user = session.get(User.class, 2);
    //4.2向返回的user对象里面设置修改之后的值
    user.setUsername("dongfangbubai");
    //4.3 调用session方法update修改
    //执行过程:到user对象里面找到uid值,根据uid进行修改
    session.update(user);

    底层代码

    Hibernate: 
        select
            user0_.uid as uid1_0_0_,
            user0_.username as username2_0_0_,
            user0_.password as password3_0_0_,
            user0_.address as address4_0_0_ 
        from
            t_user user0_ 
        where
            user0_.uid=?
    Hibernate: 
        update
            t_user 
        set
            username=?,
            password=?,
            address=? 
        where
            uid=?

    删除操作

    // 4 删除操作
    // 第一种 根据id查询对象
    User user = session.get(User.class, 2);
    session.delete(user);

    第二种删除方式

    //第二种
    User user = new User();
    user.setUid(3);
    session.delete(user);

    save和update

    在表中已经有了uid值为1的数据,再执行下面语句,有的(主键不是自动增长的)运行会报错,有的会另外增加一条数据(uid值不一样)。

    User user = new User();
    user.setUid(1);
    user.setUsername("mary");
    user.setPassword("250");
    user.setAddress("yuenan");
            
    session.save(user);

    同样下面代码,运行不会报错,

    User user = new User();
    user.setUid(1);
    user.setUsername("tom");
            
    session.update(user);

    但是导致剩余没有赋值的字段为空

    所以一般都不建议这样做。

    实体类对象状态(概念)

    1 实体类状态有三种

    (1)瞬时态:对象里面没有id值,对象与session没有关联

    User u = new User();
            u.setUsername("jack");
            u.setPassword("124");
            u.setAddress("China");
            session.save(u);

    (2)持久态:对象有id值,对象与session有关联

    User user = session.get(User.class, 1);

    (3)托管态:对象有id值,对象与session没有关联

    User user = new User();
    user.setUid(3);

    2 演示操作实体类对象的方法

    (1)saveOrUpdate方法:实现添加、实现修改

    瞬时态对象

    //1 添加操作
    User user = new User();
    user.setUsername("jack");
    user.setPassword("520");
    user.setAddress("north korean");
            
    //实体类对象状态是瞬时态,做添加操作
    session.saveOrUpdate(user);

     托管态对象

    User user = new User();
    user.setUid(2);//表中有uid为2的数据
    user.setUsername("rose");
    user.setPassword("1234");
    user.setAddress("aerbaliya");
            
    //实体类对象状态是托管态,做修改操作
    session.saveOrUpdate(user);

    查询先后结果如下所示:

    持久态对象

    //持久态
    User user = session.get(User.class,7);
    user.setUsername("rose");
            
    //实体类对象状态是持久态,做修改操作
    session.saveOrUpdate(user);
            

    运行报错,不知是不是主键没有设置动态增长的原因。

    Hibernate的一级缓存

     什么是缓存

     1 数据存到数据库里面,数据库本身是文件系统,使用流方式操作文件,效率并不是很高。

    (1)把数据存到内存中,不需要使用流的方式,可以直接读取内存中数据

    (2)把数据放到内存中,提供读取效率

    Hibernate缓存

    1 hibernate框架中提供了很多优化方式,hibernate的缓存就是一种优化方式

    2 hibernate缓存特点:

    第一类 hiberante的一级缓存

    (1)hibernate的一级缓存默认打开的

    (2)hibernate的一级缓存使用范围,是session的范围,从session创建到session关闭范围

    (3)hibernate的一级缓存中,存储数据必须是持久态数据

    第二类 hibernate的二级缓存

    (1)目前已经不使用了,替代技术redis

    (2)二级缓存默认不是打开的,需要配置

    (3)二级缓存使用范围,是sessionFactory范围

    验证一级缓存存在

    1 验证方式

    (1)首先根据uid=1查询,返回对象

    (2)其次再根据uid=1查询,返回对象

    //1 根据uid=2查询
            // 执行第一个get方法是否查询数据库,是否发送sql语句
            User user1 = session.get(User.class, 2);
            System.out.println(user1);
            
            //2 再根据uid=6查询
            //执行第二个get方法是否查询数据库,是否发送sql语句
            User user2 = session.get(User.class, 2);
            System.out.println(user2);
    Hibernate: 
        select
            user0_.uid as uid1_0_0_,
            user0_.username as username2_0_0_,
            user0_.password as password3_0_0_,
            user0_.address as address4_0_0_ 
        from
            t_user user0_ 
        where
            user0_.uid=?
    User [uid=2, username=rose, password=5678, address=aerbaliya]
    User [uid=2, username=rose, password=5678, address=aerbaliya]

    第一步执行get方法之后,发送sql语句查询数据库

    第二个执行get方法之后,没有发送sql语句,查询一级缓存内容。

    一级缓存的执行过程

    Hibernate一级缓存特性

    1 持久态自动更新数据库

    //1 根据id查询
    User user = session.get(User.class, 1);
    //2 设置返回对象
    user.setUsername("hanmeimei");
    //3 调用方法实现
    session.update(user);
            

    2 执行过程(了解)

    Hibernate事务操作

    事务相关概念

    1 什么是事务

    2 事务的特性

    3 不考虑隔离性产生问题

    (1)脏读

    (2)不可重复读

    (3)虚读

    4 设置事务隔离级别

    (1)MySQL默认隔离级别 repeatable read

    Hibernate事务代码规范写法

    1 代码结构

    try{

    开启事务

    提交事务

    }catch(){

    回滚事务

    }finally{

    关闭

    // 事务规范代码
        @Test
        public void testTx() {
            SessionFactory sessionFactory = null;
            Session session = null;
            Transaction tx = null;
            try {
                sessionFactory = HibernateUtils.getSessionFactory();
                session = sessionFactory.openSession();
                // 开启事务
                tx = session.beginTransaction();
                // 添加
                User user = new User();
                user.setUsername("xiaoma");
                ;
                user.setPassword("250");
                user.setAddress("american");
    
                session.save(user);
    
                int i = 10 / 0;
    
                // 提交事务
                tx.commit();
            } catch (Exception e) {
                // 回滚事务
                e.printStackTrace();
                tx.rollback();
            } finally {
                session.close();
                sessionFactory.close();
            }
    
        }

    Hibernate绑定session

    1 session类似于jdbc的connection,之前web阶段学过threadLocal

    2 帮我们实现与本地线程绑定session

    3 获取与本地线程绑定的session

    (1)在hibernate核心配置文件中配置

    使用单线程

    <!-- 在hibernate核心配置文件中配置 -->
    <property name="hibernate.current_session_context_class"></property>

    (2)调用sessionFactory里面的方法得到

    //提供返回与本地线程绑定的session的方法
        public static Session getSessionObject(){
            return sessionFactory.getCurrentSession();
        }

    4 获取与本地线程绑定session时候,关闭session报错,不需要手动关闭。它会自己关闭。

    不需要session.close()方法了,如果是用sessionFactory.openSession()得到的session,才需要sesssion.close();报错如下所示:

    org.hibernate.SessionException: Session was already closed
    at org.hibernate.internal.SessionImpl.close(SessionImpl.java:411)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:338)
    at com.sun.proxy.$Proxy25.close(Unknown Source)
    at cn.itcast.hibernatetest.HibernateSelect.testTx01(HibernateSelect.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

    解决办法:去掉session.close()语句即可。

    Hibernate的api使用

     Query对象

    1 使用query对象,不需要写sql语句,但是写hql语句

    (1)hql:hibernate query language,hibernate提供查询语言,这个hql语句和普通sql语句很相似

    (2)hql和sql语句区别:

    -使用sql操作表和字段

    -使用hql操作实体类和属性

    2 查询所有hql语句:

    (1) from实体类名字

    3 Query对象使用

    (1)创建Query对象

    (2)调用query对象里面的方法得到结果

                // 1 创建Query对象
                Query query = session.createQuery("from User");
                //这里加上的是实体类的名字
    
                // 2 调用query对象里面的方法得到结果
                List<User> list = query.list();
    
                for (User user : list) {
                    System.out.println(user);
                }

    Criteria对象

    1 使用这个对象查询操作,但是使用这个对象的时候,不需要写语句,直接调用方法实现

    2 实现过程

    (1)创建criteria对象

    (2)调用对象里面的方法得到结果

    //1 创建criteria对象
                    //方法里面的参数是实体类class
                    Criteria criteria = session.createCriteria(User.class);
                    //2 调用方法得到结果
                    List<User> list = criteria.list();
                    for(User user : list){
                        System.out.println(user);
                    }

    SQLQuery对象

     1 使用hibernate的时候,调用底层sql实现

     2 实现过程

    (1)创建对象

    (2)调用对象的方法得到结果

    返回list集合每部分是数组

    //1 创建对象
    // 参数普通sql语句
    SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
    //调用sqlQuery里面的方法
    //返回list集合,默认里面每部分是数组结构
    List<Object[]> list = sqlQuery.list();
                        
    for(Object[] objects : list){
    System.out.println(Arrays.toString(objects));
    }

     现在要求list返回的是对象

    要对sqlQuery进行设置,使用它的addEntity(User.class)设置吧数据放到那个实体类中去。

    //1 创建对象
                        // 参数普通sql语句
                        SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
                        
                        //返回的list中每部分是对象形式
                        sqlQuery.addEntity(User.class);
                        
                        //调用sqlQuery里面的方法
                        List<User> list = sqlQuery.list();
                        
                        for(User user : list){
                            System.out.println(user);
                        }
  • 相关阅读:
    string::push_back()
    string::pop_back
    string::insert
    string::get_allocator
    opencv —— minEnclosingCircle、fitEllipse 寻找包裹轮廓的最小圆、点集拟合椭圆
    opencv —— boundingRect、minAreaRect 寻找包裹轮廓的最小正矩形、最小斜矩形
    opencv —— approxPolyDP 生成逼近曲线
    opencv —— convexHull 寻找并绘制凸包
    opencv —— findContours、drawContours 寻找并绘制轮廓
    opencv —— equalizeHist 直方图均衡化实现对比度增强
  • 原文地址:https://www.cnblogs.com/liaoxiaolao/p/9919691.html
Copyright © 2020-2023  润新知