Hibernate(1)——基础

1 Hibernate介绍

hibernate是一个专注于数据持久化的框架, 是主流的对象 - 关系映射工具
优点:

  1. 对面向对象特性支持良好( Objective )
  2. 可移植性好
    缺点:
  3. 很难处理对特定数据库的优化
  4. 不适合大规模的批量数据处理

ORM, Object Ralationship Mapping, "对象 - 关系"映射, 指的是把对象及对象间的关系映射到数据库中的表及表间关系.
为什么需要ORM ?
java程序中偏好用对象来描述数据, 而传统的关系型数据库(如MySQL, MSSQLServer, Oracle等)偏好用表中的行(一行又包含多个列的值)来描述数据, 所以在进行应用程序开发时, 需要在这2种描述形式之间作转换, hibernate在这一方面表现非常优秀.
class(类) -> table(表)
class.property(类的属性) -> table.column(表的列)
class.oid(对象的id) -> table.pk(表的主键)

2 单表CRUD

2.1 增加

save
在这里插入图片描述

批量新增:
标准化的批量新增操作需要try catch,如果中途发生错误,需要执行回滚,如果全部执行成功,才执行提交,下面是标准化的代码:

List<UserEntity> list = new ArrayList<>();
UserEntity userEntity = new UserEntity();
userEntity.setId(10000);
userEntity.setUsername("ttt");
userEntity.setPassword("111");
list.add(userEntity);

userEntity = new UserEntity();
userEntity.setId(10001);
userEntity.setUsername("aaa");
userEntity.setPassword("222");
list.add(userEntity);

userEntity = new UserEntity();
userEntity.setId(10002);
userEntity.setUsername("bbb");
userEntity.setPassword("333");
list.add(userEntity);

SessionFactorysessionFactory = MySessionFactory.createSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
try{
	for(UserEntityuserPOJO : list) {
		System.out.println(userPOJO);
		session.save(userPOJO);
    }
	transaction.commit();  //一并提交
} catch (Exception e) {
	e.printStackTrace();
	System.out.println("批量新增执行失败");
	transaction.rollback();
} finally {
	session.close();
}

hibernate的批量插入其实就是创建一个对象,save一个对象,全部创建完毕,然后再提交,全程一定要加上try catch,当有某一条插入失败的时候,及时回滚,当然根据业务需求来决定,有时候,可能需要save一个commit一个来处理,但是不管用何种方式处理,hibernate在海量数据插入时,耗时和耗资源都会太多,原因就在于它是对象关系型数据库操作,而不是标准的SQL操作。这也是hibernate没落的一大原因。

2.2 删除

delete
在这里插入图片描述
调用session.delete方法,就可以删除对应的数据了,也是通过主键关联操作。
PS:如果在delete操作时,没有找到对应的主键id值,则会抛出异常.

批量删除:
标准化的批量删除操作需要try catch,如果中途发生错误,需要执行回滚,如果全部执行成功,才执行提交,下面是标准化的代码:

List<UserEntity> list = new ArrayList<>();
UserEntityuserEntity = new UserEntity();
userEntity.setId(10000);
list.add(userEntity);

userEntity = new UserEntity();
userEntity.setId(10001);
list.add(userEntity);

userEntity = new UserEntity();
userEntity.setId(10002);
list.add(userEntity);

SessionFactorysessionFactory = MySessionFactory.createSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
try{
	for(UserEntityuserPOJO : list) {
        Integer id = userPOJO.getId();
		userEntity = session.get(UserEntity.class, id);  //变成持久化对象
		System.out.println(userEntity);
		session.delete(userEntity);
    }
	transaction.commit();  //一并提交
} catch (Exception e) {
	e.printStackTrace();
	System.out.println("批量删除执行失败");
	transaction.rollback();
} finally {
	session.close();
}

2.3 修改

  1. upload
    在这里插入图片描述
    hibernate自身的更新是基于主键来处理,所以首先需要通过主键值,拿到一个对象,然后通过此对象的set方法,传入想修改的值,最后提交,就可以完成更新操作(PS:在实际项目中,所有展示给用户的数据,都会封装主键,当用户修改内容的时候,会把主键值传递会后台,然后后台需要判断用户传递哪些值,再进行对应修改操作)

注意,因为hibernate是通过主键值来完成后续的操作,所以大部分时候,只需要手动创建一个对应表pojo对象,set一个主键值进去,然后就可以做后续的操作。

  1. saveOrUpdate
    在这里插入图片描述
    通过使用saveOrUpdate方法,让hibernate自动检查应该是执行插入还是更新
    (PS:saveOrUpdate 和update在更新的时候,机制是不一样的,saveOrUpdate会首先查询一次对应的数据,检查是否有改变,没有改变将不做update操作,但是update不会检查数据,直接执行更新操作)

批量更新:
标准化的批量更新操作需要try catch,如果中途发生错误,需要执行回滚,如果全部执行成功,才执行提交,下面是标准化的代码:

List<Integer>id_list = new ArrayList<>();
id_list.add(1);id_list.add(2);id_list.add(3);

SessionFactory sessionFactory = MySessionFactory.createSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Iterator<Integer> iterator = id_list.iterator();
UserEntity userEntity;
try {
	while(iterator.hasNext()) {
        Integer id = iterator.next();
		userEntity = session.get(UserEntity.class, id);  //变成持久化对象
		userEntity.setPassword("000000");
		session.update(userEntity);  //把这次更新记录在缓存中
	}
	transaction.commit();  //一并提交
} catch(Exception e) {
	e.printStackTrace();
	System.out.println("批量更新执行失败");
	transaction.rollback();
} finally {
	session.close();
}

2.4 查询

  1. get(预加载)
    hibernate的查询操作,全部都是通过主键查询来完成,,
    1.基于主键查询(所以hibernate必须要求所有的表都需要有主键),查询时需要传入一个表对应的pojo对象类型和主键值,然后通过反射封装好所有的数据再返回entity对象,会直接执行sql查询。
    2.当我们使用get方法时,不管后续是否使用此对象,都会首先通过SQL将该对象查询出来,也就是常说的立即加载。
    3.get()方法执行查询时,如果我们试图得到一个id不存在的对象时,返回对象是null如果引用对象会立即报空指针异常,也就是NullPointException。

  2. load(懒加载)
    在hibernate3里面还有另外一种查询,load方式,在真正使用的时候,才会加载上来,lazy的方式。它体现的就是hibernate的lazy延迟加载属性,它是一种代理方式。
    PS:在测试时,如果没有使用返回的持久化对象,会发现,get会执行sql,而load不会执行sql语句。 Get不支持lazy,load是支持lazy的,get查询的时候,如果找不到想要的数据,返回为null,而load会抛出异常。
    1.基于主键查询,返回对应entity对象,load首先检查对象中是否存在值(不是一级缓存),如果存在,则直接获取,不会执行sql查询。
    2.Load采用的方式是延迟加载(懒加载),当我们采用load()方法加载一个对象时,并不会发送SQL语句,得到的只是一个包含了实体对象ID值的代理对象,只有当我们使用此对象时,才会发送SQL语句,当然前提是此代理对象没有此属性的值。
    3.使用load的加载方式要比get的加载方式性能好一点,因为load加载的时候,只是得到一个代理对象,当真正需要的时候才会去查询。这也代表了延迟加载与立即加载的区别。
    4.load()方法来加载对象,如果id不存在,若我们不使用该对象的任何属性,不会报异常,因为还没有执行真正的查询;但如果需要使用属性(也就是真正的去查询该对象),就会报出异常,但该异常并不是空指针,而是ObjectNotFoundException。

批量查询:
在这里插入图片描述
通过createQuery来查询表,但是要注意的时候,这里使用的hibernate自身的查询语言,所以from后面接的表所对应的pojo对象,而不是表名。

public static void main(final String[] args) throws Exception {
        final Session session = getSession();
        try {
            //根据主键查询
            Employee employee = session.get(Employee.class,"5");
            // load  在真正使用的时候,才会加载上来,lazy的方式。
            // 它体现的就是hibernate的lazy延迟加载属性,它是一种代理方式。
            System.out.println(employee.getEname()+"---"+employee.getEmploy());
            // 开启事务
            Transaction transaction = session.beginTransaction();

//            Calendar calendar = Calendar.getInstance();
//            calendar.set(Calendar.YEAR,1996);
//            calendar.set(Calendar.MONTH,6);
//            calendar.set(Calendar.DATE,26);
//            staff.setStaffBirthday(new Date(calendar.getTimeInMillis()));

            // 添加
            Employee employee2 = new Employee();
//            employee2.setId(9);
            employee2.setEname("三次修改");
            employee2.setEage("111");
            employee2.setEmploy("憨憨");
//             save:新增数据
//             update:更新数据(不会检查数据,直接执行更新操作)
//             saveOrUpdate:id存在就更新数据,id不存在就新增数据(先检查数据)
            session.saveOrUpdate(employee2);

            //删除(根据id获取对象)
//            session.delete(employee2);

            // 提交事务
            transaction.commit();
        } finally {
            session.close();// 把session里面的缓存对象 与数据库比对,如果没有就提交
            // 如果有 但是不一致 那么更新
        }
    }

3 持久化对象的三种状态

Persistence, 持久化, 指的是将java应用程序中的对象保存到数据库, 将对象属性值的更新或删除同步到数据库, 或者是把从数据库查询得到的结果集转换为对象, 简言之, 对数据库的查询, 保存, 删除, 更新操作(CRUD)都称为持久化。

  1. 瞬时对象 Transient 可以被垃圾回收机制清理掉
  2. 持久对象 Persistent 不可以被垃圾回收机制清理掉
  3. 游离对象 Detached 可以被垃圾回收机制清理掉

1、transient状态的特征:

  • 在数据库中没有与之匹配的数据
  • 没有纳入session的管理,无法执行update、delete、select更新
  • 不在session缓存里,数据库中也没有相应的记录

2、persistent状态的特征:

  • persistent状态的对象在数据库中有与之匹配的数据
  • 纳入了session的管理
  • 在清理缓存(脏数据检查)的时候,会和数据库同步
  • 在session缓存里,数据库中也有相应的记录

3、detached状态的特征:

  • 在数据库中有与之一一匹配的数据
  • 没有纳入session的管理
  • 不在session缓存里,但数据库中有相应的记录
    在这里插入图片描述
    反复用对象时,不用clean,close

session.evict(obj),会把指定的缓冲对象进行清除
session.clear(),把缓冲区内的全部对象清除,但不包括操作中的对象

在老版的idea中,如果数据库中的字段存在下划线分隔符,那么idea自动生成entity对象时,不会包含此字段内容,需要手动添加对应字段. 注意实体类的命名不能这样命名,uName,如此getter/setter方法会出错。

4 创建Maven项目步骤

步骤中解决问题:生成实体类出现hibernate please choose persistence unit错误
https://blog.csdn.net/weixin_45044097/article/details/102622596

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值