Hibernate笔记

在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一个对象
   其他略,太麻烦了
*******************************************************************************************************************






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值