1 Hibernate介绍
hibernate是一个专注于数据持久化的框架, 是主流的对象 - 关系映射工具
优点:
- 对面向对象特性支持良好( Objective )
- 可移植性好
缺点: - 很难处理对特定数据库的优化
- 不适合大规模的批量数据处理
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 修改
- upload
hibernate自身的更新是基于主键来处理,所以首先需要通过主键值,拿到一个对象,然后通过此对象的set方法,传入想修改的值,最后提交,就可以完成更新操作(PS:在实际项目中,所有展示给用户的数据,都会封装主键,当用户修改内容的时候,会把主键值传递会后台,然后后台需要判断用户传递哪些值,再进行对应修改操作)
注意,因为hibernate是通过主键值来完成后续的操作,所以大部分时候,只需要手动创建一个对应表pojo对象,set一个主键值进去,然后就可以做后续的操作。
- 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 查询
-
get(预加载)
hibernate的查询操作,全部都是通过主键查询来完成,,
1.基于主键查询(所以hibernate必须要求所有的表都需要有主键),查询时需要传入一个表对应的pojo对象类型和主键值,然后通过反射封装好所有的数据再返回entity对象,会直接执行sql查询。
2.当我们使用get方法时,不管后续是否使用此对象,都会首先通过SQL将该对象查询出来,也就是常说的立即加载。
3.get()方法执行查询时,如果我们试图得到一个id不存在的对象时,返回对象是null如果引用对象会立即报空指针异常,也就是NullPointException。 -
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)都称为持久化。
- 瞬时对象 Transient 可以被垃圾回收机制清理掉
- 持久对象 Persistent 不可以被垃圾回收机制清理掉
- 游离对象 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