Hibernate-简介

参考博客:https://www.cnblogs.com/Java-web-wy/p/6533672.html

一,Hibernate是什么

     Hibernate是一种ORM(Object/Relationship Mapping)框架,它是对象关系映射的持久层框架,它提供了JDBC的轻量级封装.

二,为什么要用Hibernate

     在不使用持久层框架的情况下,我们会自己写数据库工具来创建数据库连接,调用连接和相关接口来写操作数据的方法,每个原型都要写一个CRUD方法,冗长又繁杂.

三,Hibernate的组成

      1.Hibernate的配置文件

           (1)hibernate.cfg.xml   通常放在src文件夹

                这个配置文件由三个部分组成, 第一部分是连接数据库的信息, 第二部分是持久化类的映射文件, 第三部分是hibernate框架的相关信息,比如是否显示sql语句,使用了哪些插件信息

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8</property>
        <property name="connection.username">root</property>
        <property name="connection.password">admin</property>
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="current_session_context_class">thread</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">update</property>
        <!-- Mapping -->
        <mapping resource="com/test/pojo/Product.hbm.xml"/>
        <mapping resource="com/test/pojo/Category.hbm.xml"/>
        <mapping resource="com/test/pojo/User.hbm.xml"/>
    </session-factory>

</hibernate-configuration>

            (2) xxx.cfg.xml

               这个文件用于配置映射的类的相关信息, 要将它放在类文件的统一文件夹中

<hibernate-mapping package="com.test.pojo">
<!-- 映射的类和其对应的表 --> <class name="User" table="user_">
<!-- 主键和其增长策略 --> <id name="id" column="id"> <generator class="native"> </generator> </id>
<!-- 其他基本类型属性 --> <property name="name" />
<!-- 这是一个集合属性和其相关信息,包括表名,对应外键和多对多关系 --> <set name="products" lazy="true" table="user_product"> <key column="uid"/> <many-to-many column="pid" class="Product"/> </set> </class> </hibernate-mapping>

         

       2.核心接口

     (1)Configuration: 负责配置并启动hibernate,创建SessionFactory, 管理对象关系映射文件,管理hibernate配置信息

     

       (2)SessionFactory:负责初始化hibernate,创建session对象

  • 1、hibernate中的配置文件、映射文件、持久化类的信息都在sessionFactory中
  • 2、sessionFactory中存放的信息都是共享的信息
  • 3、sessionFactory本身就是线程安全的
  • 4、一个hibernate框架sessionFactory只有一个
  • 5、sessionFactory是一个重量级别的类 

         SessionFactory用于创建Session. 通过相关插件可以将信息二级缓存到SessionFactory中, 这样就避免了不同的Session在获取同一信息时都需要执行一次数据库访问, 而是在第一次获取了信息后, 其他Session直接从SessionFactory中获取信息.

        (3)Session:负责被持久化对象CRUD操作,得到了一个session,相当于打开了一次数据库的连接,在hibernate中,对数据的crud操作都是由session来完成, 但如果其中一个操作无法完成,其他操作也不会执行.

        Session, 当我们获取了一个对象信息, 并将它保存到Session中时, 这个数据还是瞬时状态, 会随着Session的关闭而消失,  当我们将Session中的信息传递到数据库后, 这个数据会变为持久状态, 也就是随时可以从数据库中获取而不会随着Session的关闭而消失.  Session代表着寄给数据库的信件, 将你要做的操作和要提交的信息写在Session中, 最后信息保存到了数据库中, 信件会被销毁. 而从数据库中获得的信息也会保存到Session中, 随时可以获取, 直到Session关闭

 SessionFactory sf = new Configuration().configure().buildSessionFactory();
  
        Session s = sf.openSession();
        s.beginTransaction();
 
        Product p = new Product();
        p.setName("蓝猫");
        p.setPrice(200);
        s.save(p);
 
        s.getTransaction().commit();
        s.close();
        sf.close();

       

         (4)Transaction:负责事务相关的操作, hibernate中的事务默认不是自动提交的, 只有产生了连接,才能进行事务的操作。所以只有有了session以后,才能有transaction

           在Hibernate , 任何数据操作都应该放在事务中 , 一个事务由beginTransaction()开始, 由getTransaction().commit()结束.

          

         (5)Query: 负责执行各种数据库查询,Hibernate有面向对象的数据库查询语句,HQL. 通过它可以自定义查询语句.

Query q = s.createQuery("from Product where name like :name");
        q.setParameter("name","%"+name+"%");
        List list = q.list();
        System.out.println(list);

           也依然可以使用SQL语句查询,但是操作就更困难, 

 String name = "i";
        String sql = "select * from product_ where name like '%"+name+"%'";
        NativeQuery q = s.createSQLQuery(sql);

        List<Object[]> list = q.list(); //每一个对象都成为了一个Object数组,其属性就是一个Object

        for (Object[] os : list) {
            for (Object o: os) {
                System.out.print(o+"\t");
            }
            System.out.println();
        }

四. 各种概念

 1.Criteria : 好像在5.x版本被弃用

使用Criteria进行数据查询,与HQL和SQL的区别是Criteria 完全是 面向对象的方式在进行数据查询,将不再看到有sql语句的痕迹,而HQL还有一点痕迹

 Criteria c = s.createCriteria(Product.class); //这个方法已过时
        c.add(Restrictions.like("name","%"+name+"%"));
        List<Product> lp = c.list();
        System.out.println(lp);

同时可以用Criteria 实现各种分页效果

Criteria c = s.createCriteria(Product.class);
        c.setFirstResult(2);
        c.setMaxResults(5);

2.Session的get和load操作 :  两种操作都是从数据库获得数据,但是区别在于

          get() : 这个方法一调用,就调用sql语句获取对象属性, 无论是否用到这个对象 对象不存在时返回null

          load(): 是一种懒加载方法, 只有在使用到这个对象的属性时,才会调用sql获取对象属性 对象不存在时抛出异常

Product p = (Product) s.get(Product.class, 1);
Product p2 = (Product) s.load(Product.class, 2);

3.关系延迟加载:  

 关系延迟加载需要在配置文件中设置延迟信息:

        <set name="products" lazy="true">
            <key column="cid" not-null="false" />
            <one-to-many class="Product" />
        </set>

当两个类具有多对多,一对多关系时,可以使用延迟加载,避免在创建对象后,就加载其关联的对象的信息, 占用一定的空间和时间.

只有在访问到这个属性时,才会调用sql获取其信息.

4.级联: 有四种类型,一般用在一对多, 多对多关系上

all:所有操作都执行级联操作;
none:所有操作都不执行级联操作;
delete:删除时执行级联操作; 
save-update:保存和更新时执行级联操作;

如果不使用级联, 在删除某一对象后,其有关联的表也只会将外键设置为空

5.一级缓存和二级缓存:

一级缓存: 当使用Session从数据库获得某一对象信息后, 该对象会被保存在Session中, 在之后需要的时候直接获取,而不需要再次调用sql语句从数据库中获取, 该对象会被保存直到Session被关闭

二级缓存: 添加特定插件后,Hibernate可以将获取的信息保存到SessionFactory中, 在SessionFactory与所有Session共享数据, 也就是如果由某一Session获取一个对象后,在其它Session想要获取同一对象时,不需要再调用sql获取,而是直接从SessionFactory中获取该对象.

SessionFactory sf = new Configuration().configure().buildSessionFactory();
        Session s1 = sf.openSession();

        s1.beginTransaction();
        s1.get(Product.class,8);
        System.out.println("获取目标,保存到会话1");
        s1.get(Product.class,8);
        System.out.println("再次从会话1获取目标,查看是否有一级缓存");
        s1.getTransaction().commit();

        Session s2 = sf.openSession();
        s2.beginTransaction();
        s2.get(Product.class,8);
        System.out.println("获取目标,保存到会话2");

        s2.getTransaction().commit();
        //关闭会话
        s1.close();
        s2.close();
        sf.close();

6.两种获取Session的方式: openSession和getCurrentSession

他们的区别是, openSession每次会得到一个新的Session对象

                        getCurrentSession则和线程有关,同一线程获得同一Session,不同线程获得不同Session

SessionFactory sf = new Configuration().configure().buildSessionFactory();
        //同一线程下获取Session
        Session s1 = sf.getCurrentSession();
        Session s2 = sf.getCurrentSession();

        System.out.println(s1==s2);
        s1.close();
static Session s1;
        static Session s2;
        
        Thread t1 = new Thread(){
            @Override
            public void run() {
                s1 = sf.getCurrentSession();
            }
        };
        t1.start();
        
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                s2 = sf.getCurrentSession();
            }
        });
        
        t2.start();
        t1.join();
        t2.join();

        System.out.println(s1 == s2);

另外openSession查询可以不需要事务,直接调用get(), save() , delete() 方法即可

而getCurrentSession所有操作必须放在事务中,否则会抛出异常.  同时getCurrentSession在提交事务后,Session会自动关闭

7.Query的list和iterator方法

8.乐观锁来处理脏数据

<version name="version" column="ver" type="int"></version>

通过增加version字段,用于版本信息控制, 防止在两个会话获取同一数据并修改后提交,形成脏数据.

猜你喜欢

转载自www.cnblogs.com/wqq-blog/p/10638262.html
今日推荐