资讯专栏INFORMATION COLUMN

Hibernate之CRUD与实例状态

Youngdze / 987人阅读

摘要:本文将继续介绍简单的增删改查方法和对对象实例状态的理解查询方法暂不提及。二实例状态中的对象有中状态瞬时对象持久化对象和离线对象也叫做脱管对象。持久化状态已经被持久化,并且加入到缓存中。处于游离状态的对象称为游离对象。

在上一篇《初识Hibernate》中简单介绍了在Hibernate如何加载对象和持久化对象,以及Hibernate中对象实例状态。本文将继续介绍Hibernate简单的增删改查方法和对对象实例状态的理解(查询方法暂不提及)。
一、HibernateのCRUD操作 1.1 HibernateのCreate
    @Test
    public void testCreate() {
        Session session = HibernateUtils.getSession();
        User user = new User();
        user.setId(3);
        user.setUserName("Sandy");
        user.setPassWord("aaa");
        session.save(user);
    }

注意:Hibernate事务默认是关闭的,执行后不会报错,但是数据并没有成功插入数据库。

控制台输出:Schema update complete

解决办法:手动设置事务提交

    @Test
    public void testCreate() {
        Session session = HibernateUtils.getSession();
        Transaction tx = session.beginTransaction();
        User user = new User();
        user.setId(3);
        user.setUserName("Sandy");
        user.setPassWord("aaa");
        session.save(user);
        tx.commit();
    }

控制台输出:Hibernate: insert into tbl_user (username, password, id) values (?, ?, ?)

save()方法把一个临时对象加入到Session缓存中,并持久化该临时对象,计划执行一个insert语句。
1.2 HibernateのRead

这里的查询准确来说应该称为对象加载

Hibernate中session.get()方式获取被称为对象加载,只能从数据库中加载出唯一一条记录。查询多条数据Hibernate另提供了API。
    @Test
    public void testRead() {
        Session session = HibernateUtils.getSession();
        Transaction tx = session.beginTransaction();
        User user = (User)session.get(User.class, 3);
        System.out.println(user);
        tx.commit();
    }

控制台输出:Hibernate: select user0_.id as id1_8_0_, user0_.username as username2_8_0_, user0_.password as password3_8_0_ from tbl_user user0_ where user0_.id=?
User{id=3, userName="Sandy", passWord="aaa"}

get()load()  试图从数据库加载一个实体对象时,Session先判断对象是否存在,如果存在就不到数据库中检索。返回的对象都位于Session缓存中,接下来修改了持久化对象的属性后,当Session清理缓存时,会根据持久化对象的属性变化来同步更新数据库。

区别:

​ (1)当数据库中不存在与OID对应的记录时,load()方法抛出ObjectNotFoundException异常,而get()方法返回null.

​ (2)两者采用不同的检索策略。

​ 默认情况下,load()方法采用延迟检索策略(Hibernate不会执行select语句,仅返回实体类的代理类实例,占用内存很少);而get()采用立即检索策略(Hibernate会立即执行select语句)。

使用场合:

​ (1)如果加载一个对象的目的是为了访问它的各个属性,可以用get();

​ (2)如果加载一个对象的目的是为了删除它,或者建立与别的对象的关联关系,可以用load() ;

1.3 HibernateのUpdate
更新操作并没有使用session.update()方法,直接tx.commit()便能够成功更新数据。session.upate()方法另有作用。
    @Test
    public void testUpdate() {
        Session session = HibernateUtils.getSession();
        Transaction tx = session.beginTransaction();
        User user = (User)session.get(User.class, 3);
        user.setUserName("Bob");
        user.setPassWord("123");
        // 脏数据(Dirty Data)
        // 过时数据检测(前提是该对象是持久态)
        tx.commit();
    }

控制台输出:Hibernate: select user0_.id as id1_8_0_, user0_.username as username2_8_0_, user0_.password as password3_8_0_ from tbl_user user0_ where user0_.id=?
Hibernate: update tbl_user set username=?, password=? where id=?

Session在清理缓存的时候会自动进行脏检查(dirty-check),如果发现Session缓存中的对象与数据库中相应的记录不一致,就会同步数据库。
1.4 HibernateのDelete
    @Test
    public void testDelete() {
        Session session = HibernateUtils.getSession();
        Transaction tx = session.beginTransaction();
        User user = (User)session.get(User.class, 3);
        user.setUserName("Bob");
        user.setPassWord("123");
        session.delete(user);
        tx.commit();
    }

控制台输出:Hibernate: select user0_.id as id1_8_0_, user0_.username as username2_8_0_, user0_.password as password3_8_0_ from tbl_user user0_ where user0_.id=?
Hibernate: delete from tbl_user where id=?

计划执行一个delete语句,把对象从Session缓存中删除。
1.5 saveOrUpdate
同时包含了save()和update()方法的功能。如果传入的是临时对象,就调用save()方法;如果传入的是游离对象,就调用update()方法如果传入的是持久化对象,就直接返回。
    @Test
    public void testSaveOrUpdate() {
        Session session = HibernateUtils.getSession();
        Transaction tx = session.beginTransaction();
        User user = new User();
        user.setId(5);
        user.setUserName("Sandy");
        user.setPassWord("123");
        session.saveOrUpdate(user);

        User user2 = (User)session.get(User.class, 1);
        user2.setUserName("Andy");
        user2.setPassWord("apple");
        session.saveOrUpdate(user2);
        tx.commit();
        session.close();
    }

控制台输出:Hibernate: select user_.id, user_.username as username2_8_, user_.password as password3_8_ from tbl_user user_ where user_.id=?
Hibernate: select user0_.id as id1_8_0_, user0_.username as username2_8_0_, user0_.password as password3_8_0_ from tbl_user user0_ where user0_.id=?
Hibernate: insert into tbl_user (username, password, id) values (?, ?, ?)
Hibernate: update tbl_user set username=?, password=? where id=?

update()方法把游离对象加入当前Session缓存中,计划执行update语句。当update()方法关联一个游离对象时,如果session缓存中已经有一个同类型且ID相同的持久化对象,那么update()方法会抛出NonUniqueException异常。当update()方法关联一个持久化对象时,该方法不起作用。

close():清空session缓存。

二、Hibernateの实例状态
Hibernate中的对象有3中状态,瞬时对象(TransientObjects)、持久化对象(PersistentObjects)和离线对象(DetachedObjects也叫做脱管对象)。

Java对象在Hibernate持久化层的状态:

瞬时(transient)状态:刚用new语句创建,还没有被持久化,并且不处于session缓存中(处于临时状态的对象成为临时对象)。

持久化(Persistent)状态:已经被持久化,并且加入到session缓存中。处于持久化状态的对象称为持久化对象。

游离(Detached)状态:已经被持久化,但不再处于session缓存中。处于游离状态的对象称为游离对象。

删除状态:不再处于session缓存中,并且session已经计划将其从数据库中删除。

    @Test
    public void testState() {
        Session session = HibernateUtils.getSession();
        Transaction tx = session.beginTransaction();
        // 持久态对象
        // 1.在数据库中有唯一一条记录关联 2.必须跟一个session关联(必须纳入Hibernate容器)
        User user = (User)session.get(User.class, 1);

        // 临时态
        // User user = new User();

        user.setUserName("Fancy");
        user.setPassWord("abc");

        // 脏数据(Dirty Data)过时数据检测(前提是该对象是持久态)
        tx.commit();
        // 关闭session
        session.close();

        // 游离态(Detached)
        // 1.在数据库中有唯一一条记录对应 2.当前user没有跟Hibernate的session关联(曾经跟Hibernate关联,现在没有)
        // 无法进行脏数据检测
        System.out.println(user);

        //把游离态对象变为持久态(再次纳入Hibernate容器管理,再跟一个session关联起来)
        Session session2 =HibernateUtils.getSession();
        Transaction tx2 = session2.beginTransaction();
        user.setUserName("Kathy");
        user.setPassWord("good");

        //把游离态对象同一个session关联,将对象状态变为持久态
        session2.update(user);
        tx2.commit();
    }
}

控制台输出:Hibernate: select user0_.id as id1_8_0_, user0_.username as username2_8_0_, user0_.password as password3_8_0_ from tbl_user user0_ where user0_.id=?
User{id=1, userName="Fancy", passWord="abc"}
Hibernate: update tbl_user set username=?, password=? where id=?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73488.html

相关文章

  • 使用Java编程引导JPA

    摘要:从好的方面来说,只需使用普通的就可以在不使用文件的情况下引导实现。请注意,为简洁起见,我们省略了类案例结论在本文中,我们展示了如何使用的接口和的类的自定义实现以编程方式引导实体管理器,而不必依赖传统的文件。 案例概述 大多数JPA驱动的应用程序大量使用persistence.xml文件来获取JPA实现,例如Hibernate或OpenJPA。 我们的方法提供了一种集中式机制,用于配置一...

    ymyang 评论0 收藏0
  • Hibernate问题集锦

    摘要:查询照样写就行,如下参考问题七中关于多表连接查询和返回值集合中对象问题错误的查询语句释放分析原来是查询出来的字段并不能自动转换为对象。参考问题八原因原生的语句中返回值为,而语句中的返回值位型的,网上说的主要是兼容而做的。 首先奉上Hibernate3.2 API地址:http://docs.jboss.org/hiberna...Hibernate4.3 API地址:http://do...

    niceforbear 评论0 收藏0
  • 一起来学SpringBoot | 第六篇:整合SpringDataJpa

    摘要:忽略该字段的映射省略创建数据访问层接口,需要继承,第一个泛型参数是实体对象的名称,第二个是主键类型。 SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程 上一篇介绍了Spring JdbcTempl...

    Dionysus_go 评论0 收藏0
  • Java学习路线总结,搬砖工逆袭Java架构师(全网最强)

    摘要:哪吒社区技能树打卡打卡贴函数式接口简介领域优质创作者哪吒公众号作者架构师奋斗者扫描主页左侧二维码,加入群聊,一起学习一起进步欢迎点赞收藏留言前情提要无意间听到领导们的谈话,现在公司的现状是码农太多,但能独立带队的人太少,简而言之,不缺干 ? 哪吒社区Java技能树打卡 【打卡贴 day2...

    Scorpion 评论0 收藏0
  • 【从零入门系列-2】Spring Boot 数据库实体定义实现

    摘要:文章系列从零入门系列之从零入门系列之程序结构设计说明前言本篇文章开始代码实践,系统设计从底向上展开,因此本篇先介绍如何实现数据库表实体类的设计实现。主键由数据库自动生成主要是自动增长型主键由程序控制。 文章系列 【从零入门系列-0】Sprint Boot 之 Hello World 【从零入门系列-1】Sprint Boot 之 程序结构设计说明 前言 本篇文章开始代码实践,系统...

    nemo 评论0 收藏0

发表评论

0条评论

Youngdze

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<