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. js-ES6学习笔记-Set结构和Map结构

    http://www.cnblogs.com/lonhon/ 1.ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set ...

  2. 【JS】jquery通知插件toastr

    toastr是一款非常棒的基于jquery库的非阻塞通知提示插件,toastr可设定四种通知模式:成功,出错,警告,提示,而提示窗口的位置,动画效果都可以通过能数来设置,在官方站可以通过勾选参数来生成 ...

  3. c#重起 普通路由器

    using DotNet.Utilities;using System;using System.Collections.Generic;using System.Linq;using System. ...

  4. winform利用委托delegate进行窗体间通信,相同标题已经存在??

    前段时间学习委托,感觉很模糊的样子,也做过许多实例,但是项目中一直没有用到,今天在项目中遇到一个很简单的例子,现在拿出来,做一个简单的记录. 要求:将弹出框里勾选的内容返回到主面板上. 工具:委托. ...

  5. 总结下Redux

    Redux 和 React 没有直接关系,它瞄准的目标是应用状态管理. 核心概念是 Map/Reduce 中的 Reduce.且 Reducer 的执行是同步,产生的 State 是 Immutabl ...

  6. Unreal Engine 4 Radiant UI 插件入门(三)——从蓝图中调用JS

    不知道大家有没有混淆.这篇教程说的是从蓝图中调用JS的功能(以改变H5内的内容). 在安装了UE4和RadiantUI的前提下学习这篇教程.本篇教程接着上一篇教程,建议请先看上一篇. 第一步:在网页中 ...

  7. 关于单页应用(SPA)的经验之谈

    时下SPA单页应用如火如荼,对前端乃至后端开发都带来不小的冲击和变革.笔者整理了下笔记,决定写一下以前基于iframe做单页博客的一些经验方法. 对于单页应用,笔者没有找到最官方的定义.在笔者看来,在 ...

  8. 两个java项目,跨域访问时,浏览器不能正确解析数据问题

    @Controller@RequestMapping(value = "api/item/cat")public class ApiItemCatController { @Aut ...

  9. 发博客用的一些HTML

    这个世界,在发生什么? 移动光标 <p style="background: #999999; padding: 5px; font-size: 22px;">< ...

  10. Java IO 之 BIO、NIO、AIO

    1.BIO.NIO.AIO解释 Java BIO : 同步并阻塞 (Blocking IO) 一个连接一个线程 即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不 ...