1.1Hibernate的检索方式

1.1.1Hibernate的检索方式概述

Hibernate提供了以下几种检索对象的方式:

  • 导航对象图检索方式:根据已经家就在的对象导航到其他对象。

    • Customer customer = session.get(Customer.class,1);customer.getOrders();获取客户的订单。  
  • OID检索方式:按照对象的OID来检索对象。
    • get()/load()方法来进行检索。  
  • HQL检索方式:使用面向对象的HQL查询语言。
  • QBC检索方式:使用QBC API来检索对象。这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。
  • 本地SQL检索方式:使用本地数据库的SQL查询语句。

1.1.2HQL

  • HQL(HIbernate Query Language)是面向对象的查询语言,它和SQL查询语言有些相似,在HIbernate提供的各种检索方式中,HQL是使用最广的一种检索方式。它有如下功能:

    • 在查询语句中设定各种查询条件。
    • 支持投影查询,即仅查询出对象的部分属性。
    • 支持分页查询。
    • 支持连接查询。
    • 支持分组查询,允许使用having和group by关键字。
    • 提供内置聚集函数(分组函数),如sum(),min()和max()等。
    • 能够调用用户定义的SQL函数或标准的SQL函数。
    • 支持子查询。
    • 支持动态绑定参数。
  • HQL检索方式包括以下的步骤:
    • 通过session的createQuery()方法创建一个Query对象,它包括一个HQL查询语句。HQL查询语句中可以包含命名参数。
    • 动态绑定参数。
    • 调用Query的ist()方法执行查询语句,该方法返回java.util.List类型的查询结果,在List集合中存放了符合查询条件的持久化对象。
  • Query接口支持方法链编程风格,它的setXXX()方法返回自身实例,而不是void类型。
  • HQL vs SQL:
    • HQL查询语句是面向对象的,HIbernate负责解析HQL查询语句,然后根据对象-关系映射文件中的映射信息,把HQL查询语句翻译成相应的SQL语句,HQL查询语句中的主体是域模型中的类或类的属性。
    • SQL查询语句是与关系数据库绑定在一起的。SQL查询语句中的主体是数据库表及表的字段。

1.1.3搭建环境、具体的实体类和映射文件以及核心配置文件

  • 实体类

    • Customer.java类
package cn.hibernate3.demo4;

import java.io.Serializable;
import java.util.HashSet;
/**
 * 客户实体
 */
import java.util.Set;
public class Customer implements Serializable{
    private Integer cid;
    private String cname;
    //一个客户有多个订单
    private Set<Order> orders = new HashSet<Order>();
    public Integer getCid() {
        return cid;
    }
    public void setCid(Integer cid) {
        this.cid = cid;
    }
    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    public Set<Order> getOrders() {
        return orders;
    }
    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }

}
    • Order.java类
package cn.hibernate3.demo4;

import java.io.Serializable;
/**
 * 订单实体
 */
public class Order implements Serializable{
    private Integer oid;
    private String addr;
    //订单属于某一个客户
    private Customer customer ;

    public Integer getOid() {
        return oid;
    }
    public void setOid(Integer oid) {
        this.oid = oid;
    }
    public String getAddr() {
        return addr;
    }
    public void setAddr(String addr) {
        this.addr = addr;
    }
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

}
  • 映射文件

    • Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束 -->
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.hibernate3.demo4.Customer" table="customer">
        <!-- 配置唯一标识 -->
        <id name="cid" column="cid">
            <generator class="native"/>
        </id>
        <!-- 配置普通属性 -->
        <property name="cname" column="cname" type="java.lang.String"/>
        <!-- 建立映射 -->
        <!-- 配置集合 -->
        <!--
            set标签中的name表示关联对象的属性名称

         -->
        <set name="orders">
            <!-- key标签中的column用来一对多的多的一方的外键 -->
            <key column="cno"/>
            <!-- 配置一个one-to-many -->
            <one-to-many class="cn.hibernate3.demo4.Order" />
        </set>
    </class>
</hibernate-mapping>
    • Order.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束 -->
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.hibernate3.demo4.Order" table="orders">
        <!-- 配置唯一标识 -->
        <id name="oid" column="oid">
            <generator class="native"/>
        </id>
        <!-- 配置普通属性 -->
        <property name="addr" column="addr" type="java.lang.String"/>
        <!-- 建立映射 -->
        <!--
            many-to-one标签
                属性:
                    name:关联对象的属性名称。
                    column:表中外键的名称。
                    class:关联对象的全路径。
         -->
        <many-to-one name="customer" column="cno" class="cn.hibernate3.demo4.Customer"></many-to-one>
    </class>
</hibernate-mapping>
  • 核心配置文件hibernate.cfg.xml
<?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>
    <!-- 配置数据库的基本信息 -->
    <!-- 驱动的名称 -->
    <property name="hibernate.connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <!-- 访问数据库的url -->
    <property name="hibernate.connection.url">
        jdbc:mysql:///hibernate_day03
    </property>
    <!-- 用户名 -->
    <property name="hibernate.connection.username">root</property>
    <!-- 密码 -->
    <property name="hibernate.connection.password">root</property>
    <!-- 方言 -->
    <property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    </property>
    <!-- C3P0连接池设定-->
    <!-- 使用c3po连接池  配置连接池提供的供应商-->
    <property name="connection.provider_class">
        org.hibernate.connection.C3P0ConnectionProvider
    </property>
    <!--在连接池中可用的数据库连接的最少数目 -->
    <property name="c3p0.min_size">5</property>
    <!--在连接池中所有数据库连接的最大数目  -->
    <property name="c3p0.max_size">20</property>
    <!--设定数据库连接的过期时间,以秒为单位,
        如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
    <property name="c3p0.timeout">120</property>
    <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
    <property name="c3p0.idle_test_period">3000</property>
    <!-- 可选配置 -->
    <!-- 显示SQL -->
    <property name="hibernate.show_sql">true</property>
    <!-- 格式化SQL -->
    <property name="hibernate.format_sql">true</property>
    <!-- hbm:映射 2:to ddl:create drop alter -->
    <property name="hibernate.hbm2ddl.auto">update</property>
    <mapping resource="cn/hibernate3/demo4/Customer.hbm.xml" />
    <mapping resource="cn/hibernate3/demo4/Order.hbm.xml" />

</session-factory>
</hibernate-configuration>
  • 工具类HibernateUtils.java
package cn.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * Hibernate抽取工具类
 */
public class HibernateUtils {
    private static Configuration configuration;
    private static SessionFactory sessionFactory;
    static{
        configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
    }

    public static Session openSession(){
        return sessionFactory.openSession();
    }

    public static void main(String[] args) {
        openSession();
    }
}
  • 初始化数据
  @Test
    //初始化数据
    public void demo1(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Customer customer = new Customer();
        customer.setCname("小金");

        for (int i = 0; i < 10; i++) {
            Order order = new Order();
            order.setAddr("江苏"+i);
            order.setCustomer(customer);
            customer.getOrders().add(order);
        }

        session.save(customer);

        tx.commit();
        session.close();
    }
  @Test
    //初始化数据
    public void demo1(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Customer customer = new Customer();
        customer.setCname("小名");

        for (int i = 0; i < 10; i++) {
            Order order = new Order();
            order.setAddr("北京"+i);
            order.setCustomer(customer);
            customer.getOrders().add(order);
        }

        session.save(customer);

        tx.commit();
        session.close();
    }
    • 需要配置级联关系Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束 -->
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.hibernate3.demo4.Customer" table="customer">
        <!-- 配置唯一标识 -->
        <id name="cid" column="cid">
            <generator class="native"/>
        </id>
        <!-- 配置普通属性 -->
        <property name="cname" column="cname" type="java.lang.String"/>
        <!-- 建立映射 -->
        <!-- 配置集合 -->
        <!--
            set标签中的name表示关联对象的属性名称

         -->
        <set name="orders" cascade="save-update">
            <!-- key标签中的column用来一对多的多的一方的外键 -->
            <key column="cno"/>
            <!-- 配置一个one-to-many -->
            <one-to-many class="cn.hibernate3.demo4.Order" />
        </set>
    </class>
</hibernate-mapping>

1.1.4简单查询及别名查询

  • HQL:简单查询
  @Test
    //查询所有数据
    public void demo2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer");
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.println(customer.getCname());
        }

        tx.commit();
        session.close();
    }
  • QBC:简单查询
    @Test
    //查询所有数据
    public void demo2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Criteria criteria = session.createCriteria(Customer.class);
        List<Customer> list = criteria.list();
        for (Customer customer : list) {
            System.out.println(customer.getCname());
        }

        tx.commit();
        session.close();
    }
  • SQL:简单查询
  @Test
    //查询所有数据
    public void demo2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        SQLQuery query = session.createSQLQuery("select * from customer");
        List<Customer> list = query.addEntity(Customer.class).list();
        for (Customer customer : list) {
            System.out.println(customer.getCname());
        }

        tx.commit();
        session.close();
    }
  @Test
    //查询所有数据
    public void demo2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        SQLQuery query = session.createSQLQuery("select * from customer");
        List<Object[]> list = query.list();
        for (Object[] obj : list) {
            System.out.println(Arrays.toString(obj));
        }

        tx.commit();
        session.close();
    }
  • HQL:使用别名
  @Test
    //使用别名
    public void demo3(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer as c where c.cname = ?");
        query.setString(0, "小金");
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.println(customer.getCid()+","+customer.getCname());
        }

        tx.commit();
        session.close();
    }

1.1.5排序、参数绑定和投影查询

  • 对查询结果进行排序

    • HQL
  @Test
    //排序
    public void demo4(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer c order by c.cid asc");
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.println(customer.getCid()+","+customer.getCname());
        }

        tx.commit();
        session.close();
    }
  @Test
    //排序
    public void demo4(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer c order by c.cid desc");
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.println(customer.getCid()+","+customer.getCname());
        }

        tx.commit();
        session.close();
    }
    • QBC
  @Test
    //排序
    public void demo5(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Criteria criteria = session.createCriteria(Customer.class);
        criteria.addOrder(org.hibernate.criterion.Order.asc("cid"));
        List<Customer> list = criteria.list();
        for (Customer customer : list) {
            System.out.println(customer.getCid()+","+customer.getCname());
        }

        tx.commit();
        session.close();
    }
  @Test
    //排序
    public void demo5(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Criteria criteria = session.createCriteria(Customer.class);
        criteria.addOrder(org.hibernate.criterion.Order.desc("cid"));
        List<Customer> list = criteria.list();
        for (Customer customer : list) {
            System.out.println(customer.getCid()+","+customer.getCname());
        }

        tx.commit();
        session.close();
    }
  • 分页查询:

    • setFirstResult(int firstResult);设置从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引位置。索引位置的起始值为0。默认情况下,Query从查询结果中的第一个对象开始检索。
    • setMaxResult(int maxResult);设置一次最多检索出的对象的数目。在默认情况下,Query和Criteria接口检索出查询结果中的所有对象。
    • HQL分页查询  
  @Test
    //分页
    public void demo6(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer c ");
        query.setFirstResult(0);
        query.setMaxResults(1);
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.println(customer.getCid()+","+customer.getCname());
        }

        tx.commit();
        session.close();
    }
    • QBC:分页查询  
  @Test
    //分页
    public void demo7(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Criteria criteria = session.createCriteria(Customer.class);
        criteria.setFirstResult(0);
        criteria.setMaxResults(1);
        List<Customer> list = criteria.list();
        for (Customer customer : list) {
            System.out.println(customer.getCid()+","+customer.getCname());
        }

        tx.commit();
        session.close();
    }
  • 检索单个对象

    • HQL
  @Test
    public void demo8(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer c  where c.cname = ?");
        query.setString(0, "小名");
        Customer customer = (Customer) query.uniqueResult();
        System.out.println(customer.getCid()+","+customer.getCname());

        tx.commit();
        session.close();
    }
    • QBC
  @Test
    public void demo9(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Criteria criteria = session.createCriteria(Customer.class);
        criteria.add(Restrictions.eq("cname", "小名"));
        Customer customer = (Customer) criteria.uniqueResult();
        System.out.println(customer.getCid()+","+customer.getCname());

        tx.commit();
        session.close();
    }
  • 参数绑定(HQL)

    • HIbernate的参数绑定机制依赖于JDBC API中的PreparedStatement的预定义SQL语句功能。
    • HQL的参数绑定有两种形式:
      • 按照参数位置绑定:在HQL查询语句中使用"?"来定义参数位置。
  @Test
    public void demo8(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer c  where c.cname = ?");
        query.setString(0, "小名");
        Customer customer = (Customer) query.uniqueResult();
        System.out.println(customer.getCid()+","+customer.getCname());

        tx.commit();
        session.close();
    } 
      • 使用名称方式绑定:在HQL查询语句中定义命名参数,命名参数以":"开头。  
  @Test
    public void demo8(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer c  where c.cname =:name");
        query.setParameter("name", "小名");
        Customer customer = (Customer) query.uniqueResult();
        System.out.println(customer.getCid()+","+customer.getCname());

        tx.commit();
        session.close();
    }
  • 投影查询:

    • 查询结果仅仅包含实体的部分属性。通过select关键字实现。
    • Query的list()方法返回的集合是包含数组类型的元素,每个对象数据代表查询结果的一条记录。
    • 可以在持久化类中定义一个对象的构造器来包装投影查询返回记录,使得程序能完全运用面向对象的语义来访问查询结果集。
    • 可以通过distinct关键字来保证查询结果不会返回重复元素。
    • HQL:
  @Test
    //投影操作:查询对象的某几个属性
    public void demo10(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("select c.cname from Customer c ");
        List<Object> list = query.list();
        for (Object obj : list) {
            System.out.println(obj);
        }

        tx.commit();
        session.close();
    }
  @Test
    //投影操作:查询对象的某几个属性
    public void demo10(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("select c.cname ,c.cid from Customer c ");
        List<Object[]> list = query.list();
        for (Object[] obj : list) {
            System.out.println(Arrays.toString(obj));
        }

        tx.commit();
        session.close();
    }
    • QBC
  @Test
    //投影操作:查询对象的某几个属性
    public void demo10(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        List<Object[]> list = session.createCriteria(Customer.class).setProjection(Projections.projectionList().add(Property.forName("cname")).add(Property.forName("cid"))).list();
        for (Object[] obj : list) {
            System.out.println(Arrays.toString(obj));
        }

        tx.commit();
        session.close();
    }

1.1.6HQL和QBC支持的各种运算

  • QBC

  • HQL vs QBC

1.1.7连接查询

  • SQL连接:

    • 交叉连接:

      • select * from A,B;
    • 内连接:是两个表的交集:
      • select * from A inner join B on A.字段 = B.字段;
      • 隐式内连接:
        • select * from A,B where A.字段 = B.字段;
    • 外连接:
      • 左外连接:

        • select * from A left outer join B on A.字段 = B.字段;
      • 右外连接:
        • select * from A right outer join B on A.字段 = B.字段;
  • HQL连接:
    • 交叉连接
    • 内连接
    • 隐式内连接
    • 迫切内连接
    • 左外连接
    • 迫切左外连接
    • 右外连接  
      • 示例:左外连接,返回的List<Object[]>。
  @Test
    //多表查询
    public void demo11(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer c inner join c.orders");
        List<Object[]> list = query.list();
        for (Object[] obj : list) {
            Customer customer = (Customer) obj[0];
            Order order = (Order) obj[1];
            System.out.print("customer:"+customer.getCid()+","+customer.getCname());
            System.out.print("order:"+order.getOid()+","+order.getAddr()+"\n");
        }

        tx.commit();
        session.close();
    }

        • 为什么返回的是List<Object[]),因为查询返回的字段是好几个,Hibernate将数据封装到对象数组之中。

      • 示例:迫切左外连接,返回的是List<Customer>。
  @Test
    //多表查询
    public void demo11(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Customer c inner join fetch c.orders ");
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.print(customer.getCid()+","+customer.getCname());
            Set<Order> orders = customer.getOrders();
            for (Order order : orders) {
                System.out.print(order.getOid()+","+order.getAddr());
            }
            System.out.println();
        }

        tx.commit();
        session.close();
    }

        • 为什么返回的List<Object>,因为Hibernate会每查询一个表中的某个记录,就将记录封装到对象之中,这样就会产生重复的结果?怎么办?使用distinct关键字即可,消除重复的结果。
  @Test
    //多表查询
    public void demo11(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("select distinct c from Customer c inner join fetch c.orders ");
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.print(customer.getCid()+","+customer.getCname());
            Set<Order> orders = customer.getOrders();
            for (Order order : orders) {
                System.out.print(order.getOid()+","+order.getAddr());
            }
            System.out.println();
        }

        tx.commit();
        session.close();
    }

  • 连接查询:HQL vs QBC

1.1.8离线条件查询

  @Test
    //多表查询
    public void demo12(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //在web层
        DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
        criteria.add(Restrictions.eq("cname", "小名"));

        //在dao层:web层将Criteria传递到service层,然后service层再将Criteria传递到dao层
        //这样在dao层,就可以从session中获取离线的Criteria。
        Criteria criteria2 = criteria.getExecutableCriteria(session);
        List<Customer> list = criteria2.list();
        for (Customer customer : list) {
            System.out.println(customer.getCid()+","+customer.getCname());
        }

        tx.commit();
        session.close();
    }

 1.1.9HQL和QBC检索的总结

比较方面 HQL检索 QBC检索
可读性 优点:和SQL相近,易读。 将语句肢解成一组Criteria,较差。
功能 支持各种查询。 不支持分组查询和子查询。有限制。
查询语句形式 基于字符串形式的HQL 更加面向对象。
何时被解析 运行时被解析。 编译时被解析,更易排错。
可扩展性 不具扩展性。 用户可扩展Criteria接口。
对动态查询语句的支持 支持动态查询,编程麻烦。 适合动态生成查询语句。

      

    

        

      

    

  

1.2Hibernate的抓取(检索)策略  

1.2.1区分延迟和立即检索

  • 立即检索:

    • 当执行某行代码的时候,马上发出SQL语句进行查询。
    • get();
  • 延迟检索:
    • 当执行某行代码的时候,不会马上发出SQL语句进行查询。当真正使用这个对象的时候才会发送SQL语句。
    • load();  
  • 类级别的检索和关联级别的检索。
    • 类级别的检索:

      • <class>标签上配置lazy="true/false"。
    • 关联级别的检索:
      • <set>/<many-to-one>标签上配置lazy="true/false"。  
  • 从一的一方去关联多的一方:
    • <set>

      • fetch:控制SQL语句的类型。

        • join:发送迫切左外连接的SQL查询关联对象。fetch="join"那么lazy被忽略。
        • select:默认值。发送多条SQL查询关联对象。
        • subselect:发送子查询查询关联对象。(需要使用Query接口测试)。
      • lazy:控制关联对象的检索是否采用延迟。
        • true:默认值。查询关联对象的时候使用延迟检索。
        • false:查询关联对象的时候不使用延迟检索。
        • extra:极其懒惰的。 
      • 如果fetch是join的类型,那么lazy属性可以忽略。
  • 从多的一方关联一的一方:
    • <many-to-one>

      • fetch:控制SQL语句的类型。

        • join:发送一个迫切左外连接查询关联对象。fetch="join",lazy属性会被忽略。
        • select:发送多条SQL检索关联对象。  
      • lazy:控制关联对象的检索是否采用延迟。
        • false:不延迟。
        • proxy:使用代理。
        • no-proxy:不使用代理。

  

1.3Hibernate的事务处理  

  • 事务:

    • 事务就是逻辑上的一组操作,要么全部成功,要么全部失败。
  • 事务特性:
    • 原子性:事务一组操作不可分割。
    • 一致性:事务的执行前后,数据完整性要保持一致。
    • 隔离性:一个事务在执行的过程中不应该受到其他事务的干扰。
    • 持久性:一旦事务结束,数据就永久保存到数据库里。
  • 如果不考虑事务的隔离性,会引发一些安全性问题:
    • 5大类问题:3类读问题2类写问题。

      • 读问题:

        • 脏读:一个事务读取到另一个事务未提交数据。
        • 不可重复读:一个事务已经读取到另一个事务已经提交数据(update),导致查询结果不一致。
        • 虚读:一个事务读到另一个事务已经提交的数据(insert),导致查询结果不一致。
      • 避免三种读的问题:
        • 设置事务的隔离级别:

          • 未提交读:以上三种读问题  都有可能发生。
          • 已提交读:避免脏读,但是不可重复读和虚读可能发生。
          • 重复读:避免脏读和不可重复读,但是虚度是有可能发生的。
          • 串行读:可以避免以上三种读问题。
      • 在Hibernate中设置事务的隔离级别:
        • 在核心配置文件中:

          • <property name="hibernate.connection.isolation">4</property>
  <!--
        1—Read uncommitted isolation
        2—Read committed isolation
        4—Repeatable read isolation
        8—Serializable isolation
     -->
    <property name="hibernate.connection.isolation">4</property>
      • 写问题:丢失更新。

        • 悲观锁:
        • 乐观锁:
  • 线程绑定session:
    • 在hibernate.cfg.xml中配置一个:

      • <property name="hibernate.current_session_context_class">thread</property>
    • 使用SessionFactory中的getCurrentSession();方法
      • 底层就是ThreadLocal。                                  

Hibernate(三)的更多相关文章

  1. 简单理解Hibernate三种状态的概念及互相转化

    本文描述了Hibernate三种状态的概念及互相转化.Java对象的生命周期中有三种状态,而且互相转化.它们分别是临时状态,持久化状态,以及游离状态. AD:WOT2015 互联网运维与开发者大会 热 ...

  2. [转]hibernate三种状态详解

    本文来自 http://blog.sina.com.cn/u/2924525911 hibernate 三种状态详解 (2013-04-15 21:24:23) 转载▼   分类: hibernate ...

  3. hibernate三种状态

    转自:http://www.cnblogs.com/xiaoluo501395377/p/3380270.html 学过hibernate的人都可能都知道hibernate有三种状态,transien ...

  4. hibernate(三) 一对多映射关系

    序言 前面两节讲了hibernate的两个配置文件和hello world!.还有hibernate的一级缓存和三种状态,基本上hibernate就懂一点了,从这章起开始一个很重要的知识点,hiber ...

  5. Hibernate三种状态的转换

    hibernate的状态 hibernate的各种保存方式的区(save,persist,update,saveOrUpdte,merge,flush,lock)及 对象的三种状态 hibernate ...

  6. Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用 引自http://www.blogjava.net/TiGERTiAN/archive/2008/10/25/236519.html

    Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object ...

  7. Hibernate(三)——框架中的关系映射

    在设计数据库时我们会考虑,表与表之间的关系,例如我们前边经常提到的一对一,一对多,多对多关系,在数据库中我们通过外键,第三张表等来实现这些关系.而Hibernate时间实体类和数据库中的表进行的映射, ...

  8. hibernate 三种状态的转换

    一.遇到的神奇的事情 使用jpa操作数据库,当我使用findAll()方法查处一个List的对象后,给对这个list的实体进行了一些操作,并没有调用update 或者 saveOrUpdate方法,更 ...

  9. SSH框架之-hibernate 三种状态的转换

    一.遇到的神奇的事情 使用jpa操作数据库,当我使用findAll()方法查处一个List的对象后,给对这个list的实体进行了一些操作,并没有调用update 或者 saveOrUpdate方法,更 ...

  10. Hibernate三种状态,缓存,以及update更新问题

    一. Hibernate中对象的三种状态 1. 瞬时状态(transient) 当我们通过Java的new关键字来生成一个实体对象时,这时这个实体对象就处于自由状态,此时该对象只是通过JVM获得了一块 ...

随机推荐

  1. 记一次redis挂机导致的服务雪崩事故~不对,是故事

    事故时常有,最近特别多!但每次事故总会有人出来背锅!如果不是自己的锅,解决了对自己是一种成长,如果是自己的锅,恐怕锅大了,就得走人了,哈哈哈... 这不,最近又出了一个锅:从周五开始,每天到11点就不 ...

  2. web前段学习2016.6.6

    目前上网的方式:手机平板电脑移动端:智能手机.平板PC:电脑.笔记本运行在移动端的东西:APPios:object-candroid:javapc端的东西:桌面应用程序 c++ 我们上网的方式都是通过 ...

  3. [UWP]浅谈按钮设计

    一时兴起想谈谈UWP按钮的设计. 按钮是UI中最重要的元素之一,可能也是用得最多的交互元素.好的按钮设计可以有效提高用户体验,构造让人眼前一亮的UI.而且按钮通常不会影响布局,小小的按钮无论怎么改也不 ...

  4. EF查询百万级数据的性能测试--多表连接复杂查询

    相关文章:EF查询百万级数据的性能测试--单表查询 一.起因  上次做的是EF百万级数据的单表查询,总结了一下,在200w以下的数据量的情况(Sql Server 2012),EF是可以使用,但是由于 ...

  5. Django学习(一)---基本配置及创建项目、应用

    安装:在Django官网下载最新版Django然后通过pip安装即可 一.创建项目 进入文件夹,打开cmd窗口,输入django-admin startproject myblog(项目名) 二.创建 ...

  6. Unreal Engine 4 Radiant UI 入门教程(零)在场景中摆放网页

    相关的学习资源: https://forums.unrealengine.com/showthread.php?12097-PLUGIN-RadiantUI-SDK-UIs-HUDs-Interact ...

  7. HDU 1728 逃离迷宫(DFS)

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1728 题目: 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)  ...

  8. Spring MVC 以.html为后缀名访问获取数据,报406 Not Acceptable错误。

    如题,最近以spring mvc作为后台框架,前端异步获取数据时(.html为后缀名的访问方式),报406 Not Acceptable错误.当初都不知道啥原因,前后台都没报错就是返回不了数据,于是查 ...

  9. java 线程之concurrent中的常用工具 CyclicBarrier

    一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...

  10. .NET CORE——Console中使用依赖注入

    我们都知道,在 ASP.NET CORE 中通过依赖注入的方式来使用服务十分的简单,而在 Console 中,其实也只是稍微绕了个小弯子而已.不管是内置 DI 组件或者第三方的 DI 组件(如Auto ...