在Hibernate开发过程中通常会用到5个核心接口,分别是Configuration接口,SessionFactory接口,Session接口,Transaction接口 Query接口,Criteria接口,通过这些接口可以对持久化对象进行操作,还可以进行事务控制。 Hibernate持久化操作的主要步骤 1,初始化Hibernate,构建Configuration实例,这一步用来读取Hibernate核心配置文件和映射文件信息到Configuration对象中 2,创建SessionFactory实例,通过Configuration对象读取到的配置文件信息并创建SessionFactory,并将Configuration对象中的所有配置 文件信息存入SessionFactory内存中 3,创建Session实例,建立数据库连接,Session是通过SessionFactory打开的,创建一个Session对象就相当于建立一个新的数据库连接 4,创建Transaction实例,开启一个事务。Transaction用于事务管理,一个Transaction对象对应的事务可以包括多个操作。 在使用Hibernate进行增,删,改操作的时候,必须先创建Transaction对象 5,利用Session接口通过的各种方法进行持久化操作 6,提交事务,对实体对象持久化操作后,必须提交事务 7,关闭Session,断开与数据库的连接 需要注意的是,Hibernate的事务默认是不开启的,如果执行增删改操作,需要手动开启事务来控制,如果只做查询操作,可以不开启事务。 ****************************************************************************************************************** 下面先讲讲Query对象和Criteria对象,这两个对象都是用于查询操作,不同的是Criteria可以用于条件查询,分页查询等。 Query 1,编写HQL语句,HQL语句是面向对象的类似SQL的语句,只不过把数据库表名替换成类名 2,调用session.createQuery创建查询对象 3,如果HQL语句包含参数,则调用Query的setXxx设置参数 4,调用Query对象的list()或uniqueResult()方法执行查询 例子 //Query对象查询 @Test public void queryTest() { String hql = "from TeacherinfoEntity"; Query query = session.createQuery(hql); List<TeacherinfoEntity> list = query.list(); for (TeacherinfoEntity teacher:list) { System.out.println(teacher); } } Criteria对象等方法在Hibernate5以后不支持,以后再讲代替方法 ******************************************************************************************************************* Hibernate的测试类 public class TeacherTest { private SessionFactory sessionFactory; private Session session; private Transaction transaction; TeacherinfoEntity teacher; @Before public void init() { Configuration config = new Configuration().configure(); sessionFactory = config.buildSessionFactory(); session=sessionFactory.openSession(); transaction=session.beginTransaction(); } @Test public void addTest() { teacher = new TeacherinfoEntity("加藤鹰老师","987654321","123456"); session.save(teacher); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); System.out.println(teacher); } } ******************************************************************************************************************* Hibernate的持久化状态和一级缓存 Hibernate是持久层的ORM映射框架,专注于数据的持久化工作,所谓的持久化,就是将内存中的数据永久存储到关系型数据库中 持久化对象的状态 瞬时态 瞬时态的实例是由new命令创建,开辟内存空间的对象,不存在持久化标识OID(相当于主键值),尚未与Hibernate Session关联, 在数据库中也没有记录,瞬时态的对象在内存中是孤立存在的,与数据库中的数据无任何关联,仅是一个信息携带的载体。 TeacherinfoEntity teacher = new TeacherinfoEntity("加藤鹰老师","987654321","123456"); 1,当一个对象被执行new关键字创建后,该对象处于瞬时态 2,当Session缓存执行Session.delete(对象),持久态对象转化为了瞬时态对象 3,当托管态设置UID为空时,托管态转变为瞬时态,teacher.setTeacherId(null); 持久态 持久态的对象存在持久化标识OID,加入到了Session缓存中,并且相关联的Session没有关闭,在数据库中有对应的记录, 每条记录只对应唯一的持久化对象,需要注意的是,持久态对象是在事务还未提交前变成持久态的。 session.save(teacher); 1,当直接执行Session的get(),load(),find(),或iterate()等方法从数据库里查询对象时,查询到的对象也处于持久态 2,当瞬时态对象执行Session的save()或saveOrUpdate()方法后,该对象将被放入Session缓存中,对象进入持久态 3,当托管态对象执行update(),saveOrUpdate(),look()操作后,托管态对象就过度到了持久态 托管态 当某个持久化状态的实例与Session的关联被关闭时就变成了托管态,托管态对象存在持久化标识OID,并且仍然与数据库中的数据存在关联 只是失去了与当前Session的联系,托管态对象发生改变时,Hibernate不能检测到。 System.out.println(teacher); 1,当持久态对象执行evict(),close()或clear()操作后,对象进入托管态 2,当瞬时态设置UID后,瞬时态变为托管态,teacher.setTeacherId(1); 瞬时态对象和持久态对象的区别:持久态对象与Session进行了关联并且OID有值 托管态对象与持久态对象的区别:托管态对象没有了Session关联 ******************************************************************************************************************* 一级缓存 Hibernate的一级缓存就是指Session缓存,Session缓存是一块内存空间,用来存放相互管理的java对象, Hibernate的一级缓存的作用就是减少对数据库的访问次数,如果Session中有我要的对象,就直接返还给我, 如果没有就查数据库并保存进Session中再返还给我。 Hibernate的刷出缓存 Session能够在某些时间点,按照缓存中对象的变化,执行相关的SQL语句来同步更新数据库,这一过程被称为刷出缓存 默认情况下,Session在如下几种时间点刷出缓存 1,当应用程序调用Transaction的commit()方法时,该方法先刷出缓存(调用session.flush()方法),然后再向数据库提交事务。 2,当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先刷出缓存,以保证查询结果能够反映持久化对象的最新状态 3,调用Session的flush()方法 Hibernate快照 Session的刷出功能,session.flush()方法就是依赖与Hibernate的快照 Hibernate向一级缓存存放数据时,同时复制一份数据到Hibernate快照中,当使用commit()方法提交事务时, 就会执行session.flush()方法,其原理是,使用UID判断一级缓存中的对象和快照中的对象是否一致,如果不一致则执行update语句同步数据库 如果一致就不执行update语句,Hibernate快照的作用就是确保一级缓存中的数据与数据库中的数据一致。 一级缓存的常用操作 1,session.flush(),利用Hibernate的快照,同步更新数据库 2,session.clear(),清除缓存中的所有持久态对象,session.evict(),清除缓存中某个对象 3,session.refresh(),重新查询数据库并更新Hibernate快照区和一级缓存使得与数据库保持一致。 ************************************************************************************************************** Hibernate使用实体类注解后,可以不用写实体类的配置文件,*。hbm.xml ************************************************************************************************************** Hibernate的关联关系映射 数据库中多表之间存在着三种关系,也就是系统设计中的三种实体关系,系统设计的三种实体关系分别是:多对多,一对多和一对一关系。 在数据库中,实体表之间的关系映射是采用外键来描述的,具体如下: 一对多,在多的一方,添加一的一方的主键作为外键。 多对多,产生中间关系表,引入两张表的主键作为外键,两个主键成为联合主键。 一对一,在任意一方引入对方主键作为外键(开发中使用非常少) 总结Hibernate的关联映射 1,不管是一对多还是多对多,只要是单向关联映射,都不需要设置反转,即mappedBy="" 只有在双向关联映射时才需要设置反转,通常,一对多中,在一的一方设置反转, 多对多中,随便哪一方设置反转都可以。 2,级联设置只有设置在主控类中才能生效,当设置在主控类中时,保存主控类,被控类也被自动保存 当设置在被控类中,保存被控类,主控类的信息不会被保存。在一对多中,多的一方是主控类 在多对多中,配置了@JoinTable(name = "s_c",joinColumns = {@JoinColumn(name="sid")}, inverseJoinColumns = {@JoinColumn(name="cid")}) 就是主控类 3,mappedBy属性的值是主控类的外键属性,记住,是属性名 @JoinColumn()中name的值是表的外键 **************************************************************************************************************** 今天晚上记记Hibernate的事务处理和二级缓存 在数据库操作中,一项事务是由一条或多条操作数据库的SQL语句组成的一个不可分割的工作单元,当事务中所有操作都正常完成时,整个事务才能被提交 到数据库中,如果有一项操作没有完成,则整个事务会被回滚。 事务的特性 ACID,即原子性,一致性,隔离性,持久性 Hibernate的事务处理 Hibernate事务处理方式之悲观锁 悲观锁是指在每次操作数据库时,总是悲观地认为会有其他事务也会来操作同一数据,因此,在整个数据处理过程中,将会把数据处于锁定状态 在Hibernate中,用户可以显式地设定锁模式,通常在应用中会设定如下两种锁模式 LockMode.UPGRADE,mysql数据库支持 LockMode.UPGRADE_NOWAIT,Oracle数据库特有的锁模式 悲观锁的使用: 配置Hibernate事务,在hibernate.cfg.xml中 <property name="hibernate.connection.isolation">2</property> 在实体类中查询时加上锁模式 TeacherinfoEntity teacher2 = session.load(TeacherinfoEntity.class, 2,LockMode.PESSIMISTIC_READ); 锁这部分太复杂了,不是短时间能完成的,所以打算先用着再说 Hibernate事务处理方式之乐观锁 乐观锁通常认为许多事务同时操作同一数据的情况很少发生,所以乐观锁不做数据库层次的锁定,而是基于数据版本(Version)标识 实现程序级别上的锁定机制。 数据版本标识 是指通过为数据库表增加一个Version字段,实现在读取数据时,将版本号一同读出,之后更新数据时,将此版本号加1, 在提交数据时,将现有版本号与数据库表对应记录的版本号进行对比,如果提交数据的版本号大于数据库表中 的版本号,则允许更新数据,否则禁止更新数据 具体步骤,数据库表中增加version字段,实体类中增加相应的属性,并使用@Version标识 Hibernate的二级缓存 Hibernate在查询数据库时,会将查询到的数据存放到一级缓存Session中和二级缓存SessionFactory中,一级缓存关闭后 二级缓存中仍然有数据,但这个数据,即对象不再和一级缓存中的对象相同,存放在二级缓存中的是散装数据,取的时候会重新new一个对象 其他略,太麻烦了 *******************************************************************************************************************
Hibernate笔记
最新推荐文章于 2020-07-30 11:10:27 发布