hibernate学习(二)

回家呆了两个多星期,本该一星期学完的hibernate框架被拖了这么久。今天才把第二天的教程看完。做个简单的总结。

第一节 常用的主键生成策略

主键生成策略有几个,主要使用的是uuid和native

  • uuid 通过hibernate自动生成一个32位的16进制字符串作为唯一标识符 实体类变量类型String
  • native hibernate根据数据库类型自动选择 生成一个自增的标识符 实体类变量类型Integer

测试了一下increment策略,其同样是产生一个Integer类型自增主键,不过在生成时是先查询主键最大的数字然后根据这个数字在添加新的数据。sql语句如下

Hibernate:  select max(hid)  from t_home
Hibernate:  insert  into t_home (attr, tel, hid)  values  (?, ?, ?)

如果是native策略 则将主键在数据库中设置为自增。做添加操作时不会对主键进行设置,sql语句如下

Hibernate:  insert  into t_home (attr, tel)  values  (?, ?)

疑惑: 几种生成策略中没有发现与通过注释设置主键相同的方式。。。

第二节 CRUD操作

  • 增加 session.save(user);
    @Test
    public void testSave() {
        Session session = HbmUtil.getSession();
        Transaction tx = session.beginTransaction();

        User user = new User();
        user.setUid(555); // 需要注意的是这里设置主键是无效的 hibernate会根据主键生成策略自动设置
        user.setName("lee");
        user.setPass("333");
        session.save(user);
        
        tx.commit();
        session.close();
    }
  • 删除 session.delete(user);
    @Test
    public void testDelete() {
        Session session = HbmUtil.getSession();
        Transaction tx = session.beginTransaction();
        // 第一种 获取持久化对象后删除
        User user = session.get(User.class, 2);
        session.delete(user);
        
        // 第二种 通过托管态对象删除 不推荐
        User user2 = new User();
        user2.setUid(1);
        session.delete(user2);
        
        tx.commit();
        session.close();
    }
Hibernate:  delete   from  t_user  where uid=?
根据sql语句可知只要实体类中存在主键id且数据库中存在对应记录 就能进行删 若记录不存在则报错
  • 修改 session.update(user);
    @Test
    public void testUpdate() {
        Session session = HbmUtil.getSession();
        Transaction tx = session.beginTransaction();
        // 第一种 通过持久化对象自动修改
        User user = session.get(User.class, 4);
        user.setName("333333");
        
        // 第二中 使用update修改
        User user2 = session.get(User.class, 3);
        user2.setPass("nihao");
        session.update(user2);
        
        // 第三中 通过托管态对象进行修改 必须所有字段都进行设置 不然就会用null代替 且主键必须存在不然报错 不推荐
        User user3 = new User();
        user3.setUid(11);
        user3.setName("托管态");
        user3.setPass("修改");
        session.update(user3);

        tx.commit();
        session.close();
    }
Hibernate: update t_user  set uname=?, upass=?  where uid=?
从sql语句看出每次都是全部更新 因此托管态的实体类必须对每个值都进行设置

什么是托管态,持久态下面有介绍

  • 查询 session.get(User.class, id);
    @Test
    public void testQuery() {
        Session session = HbmUtil.getSession();
        Transaction tx = session.beginTransaction();
        
        User user = session.get(User.class, 1);
        System.out.println(user);
        
        tx.commit();
        session.close();
    }
Hibernate:  select uid, uname, upass from t_user where uid=?

第一个值传入实体类的class有没有和DBUtils里的ResultSetHandler接口很像,这只是个简单的查询,更复杂的在后面会有讲解

第三节 实体类的三种状态与saveOrUpdate

  • 瞬时态 与session无关 不存在主键id
User user = new User();
user.setName("你好");
user.setPass("瞬时态");
  • 持久态 与session相关 存在主键id
User user = session.get(User.class, 4);
// 持久态可实现自动更新 原因是内部存在快照 在事务提交前会进行对比 不一样则更新
user.setName("自动更新");
  • 托管态 与session无关 存在主键id
User user = new User();
user.setUid(6);
user.setName("托管态");
user.setPass("嗨~");
  • 三态的相互转换
 * 瞬时态:执行session.save方法转化为持久态  添加id变托管态
 * 持久态:session.delete转化瞬时 session.clear转化托管
 * 托管态:删除id转发瞬时 session.update session.saveOrUpdate转化持久
  • savaOrUpdate具体执行的操作
    /**
     * 测试SaveOrUpdate具体执行方式
     * 实体类对象是瞬时态时做save操作
     * 实体类对象是托管态时做update操作
     * 实体类对象是持久态时做update操作
     */
    @Test
    public void testSaveOrUpdate() {
        Session session = HbmUtil.getSession();
        Transaction tx =session.beginTransaction();

        // 瞬时态
        User user = new User();
        user.setName("你好");
        user.setPass("瞬时态");
        
//      session.saveOrUpdate(user);
        
        // 托管态
        // 托管态中的id在数据库中不存在则 报错
        User user1 = new User();
        user1.setUid(11);
        user1.setName("又是托管态的修改");
        user1.setPass("托管态");
        
        session.saveOrUpdate(user1);
        
        // 持久态
        User user2 = session.get(User.class, 4);
        user2.setName("持久态哈");
        
//      session.saveOrUpdate(user2);
        
        tx.commit();
        session.close();
    }

总结: 实体类带有id 且该id对应的记录在数据库中存在进行update操作 否则save操作

第四节 事务处理的标准写法

package cn.lkangle.twoday;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;

public class Standard {
    @Test
    public void test() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            User user2 = new User();
            user2.setName("回滚");
            user2.setPass("测试");
            session.save(user2);
            
//          int s = 100/0;
            
            User user = session.get(User.class, 2);
            user.setName("测试回滚");
            session.update(user);
            
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("出现异常 回滚事务");
            tx.rollback();
        } finally {
            System.out.println("关闭session");
            session.close();
        }
    }
}

没有出现异常则正常提交事务,事务回滚写在catch中,出现异常则回滚事务,最后关闭session

第五节 绑定本地session

通过将session绑定在本地线程中达到一次事务中只存在一个session

  • 配置hibernate.cfg.xml文件 添加下句
 <!-- 绑定本地session 放在本地线程中 共三个值 一般用thread与本地线程绑定 -->
<property name="hibernate.current_session_context_class">thread</property>
  • 通过 SessionFactory.getCurrentSession()获取
  • 例子
    LocalSession.java类
package cn.lkangle.twoday;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.lkangle.util.HbmUtil;

public class LocalSession {
    @Test
    public void testLocal(){
        Session session = HbmUtil.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        new addUser().saveUser();
        
        tx.commit();
    }
}

addUser.java类

package cn.lkangle.twoday;

import org.hibernate.Session;

import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;

public class addUser {
    public void saveUser() {
        User user = new User();
        user.setName("新文件中添加");
        user.setPass("测试事务中session处理");
        
        Session session = HbmUtil.getCurrentSession();
        session.save(user);
    }
}

绑定本地的session不需要对session进行关闭,在线程结束后会自动关闭。

第六节 hibernate缓存

  • 一级缓存: 默认开启 作用域在session
    测试一级缓存存在
package cn.lkangle.twoday;
/**
 * 一级缓存作用域session 从session创建到session关闭
 * 证明存在一级缓存 
 * @author lbxx
 */

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;

public class Cache {
    @Test
    public void cacheTest() {
        Session session = HbmUtil.getSession();
        Transaction tx = session.beginTransaction();
        
        User user = session.get(User.class, 1);
        System.out.println(user);
        
        /**
         * 每次查询都会先在一级缓存中查找数据 如果发现则直接取出 如果没有发现则进行数据库查询
         * 一级缓存默认打开 保存持久态的数据
         */
        User user2 = session.get(User.class, 1);
        System.out.println(user2);
        
        tx.commit();
        session.close();
    }
}

两次查询只进行一次sql操作,第二次直接从缓存中获取

Hibernate: 
    select
        user0_.uid as uid1_2_0_,
        user0_.uname as uname2_2_0_,
        user0_.upass as upass3_2_0_ 
    from
        t_user user0_ 
    where
        user0_.uid=?
name--> 新文件中添加 pass--> 测试事务中session处理
name--> 新文件中添加 pass--> 测试事务中session处理
  • 二级缓存: 用户控制开启 作用域在SessionFactory
    二级缓存暂未介绍

第七节 hibernate查询api 查询表中所有数据

调用两步走

  1. 创建对象
  2. 执行对象中方法
  • Query对象
package cn.lkangle.twoday;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;

public class QueryTest {
    @Test
    public void testQuery() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            Query<User> query = session.createQuery("from User");
            
            List<User> list = query.list();
            
            for (User user : list) {
                System.out.println(user);
            }
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
}
  • Criteria对象
package cn.lkangle.twoday;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;

public class CriteriaTest {
    @Test
    public void testCriteria() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            Criteria criteria = session.createCriteria(User.class);
            List<User> list = criteria.list();
            
            for (User user : list) {
                System.out.println(user);
            }
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
}
  • SQLQuery对象
    该对象默认查询返回值类型是数组 可以通过addEntity方法设置为对象类型
package cn.lkangle.twoday;

import java.util.Arrays;
import java.util.List;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;

public class SQLQueryTest {
    @Test
    public void sqlqueryTest() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
            
            List<Object[]> list = sqlQuery.list();
            
            for (Object[] objects : list) {
                System.out.println(Arrays.toString(objects));
            }
            
            sqlQuery.addEntity(User.class);
            
            List<User> list2 = sqlQuery.list();
            
            for (User user : list2) {
                System.out.println(user);
            }
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
}

更多的查询操作会在第四天进行讲解
有点疑惑的是这些方法好像都被弃用了

估计后面会有新的方式吧

end、、、

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 1.主键生成策略 1.1 主键的两种类型 自然主键:把数据表中的某一业务字段作为表的主键。如一张用户表中,把用户的...
    Wizey阅读 536评论 0 3
  • 本文包括:1、Hibernate的持久化类2、Hibernate 持久化对象的三个状态(难点)3、Hibernat...
    廖少少阅读 1,435评论 0 13
  • 这部分主要是开源Java EE框架方面的内容,包括Hibernate、MyBatis、Spring、Spring ...
    杂货铺老板阅读 1,343评论 0 2
  • Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库...
    兰缘小妖阅读 1,195评论 1 18
  • 我能想到如果我要演电视剧关于做衣服的最终成为一名出色的世界一流的服装设计师。我就能在现实生活中搜集现实相关的经验。...
    向上_8cd7阅读 247评论 6 0