Java的Hibernate框架数据库操作中锁的使用和查询类型

 Hibernate与数据库锁
一、为什么要使用锁?

要想弄清楚锁机制存在的原因,首先要了解事务的概念。
事务是对数据库一系列相关的操作,它必须具备ACID特征:

  • A(原子性):要么全部成功,要么全部撤销。
  • C(一致性):要保持数据库的一致性。
  • I(隔离性):不同事务操作相同数据时,要有各自的数据空间。
  • D(持久性):一旦事务成功结束,它对数据库所做的更新必须永久保持。

我们常用的关系型数据库RDBMS实现了事务的这些特性。其中,原子性、
一致性和持久性都是采用日志来保证的。而隔离性就是由今天我们关注的
锁机制来实现的,这就是为什么我们需要锁机制。

如果没有锁,对隔离性不加控制,可能会造成哪些后果呢?

  1. 更新丢失:事务1提交的数据被事务2覆盖。
  2. 脏读:事务2查询到了事务1未提交的数据。
  3. 虚读:事务2查询到了事务1提交的新建数据。
  4. 不可重复读:事务2查询到了事务1提交的更新数据。

下面来看Hibernate的例子,两个线程分别开启两个事务操作tb_account表中
的同一行数据col_id=1。

package com.cdai.orm.hibernate.annotation; 

import java.io.Serializable; 

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table; 

@Entity
@Table(name = "tb_account")
public class Account implements Serializable { 

  private static final long serialVersionUID = 5018821760412231859L; 

  @Id
  @Column(name = "col_id")
  private long id; 

  @Column(name = "col_balance")
  private long balance; 

  public Account() {
  } 

  public Account(long id, long balance) {
    this.id = id;
    this.balance = balance;
  } 

  public long getId() {
    return id;
  } 

  public void setId(long id) {
    this.id = id;
  } 

  public long getBalance() {
    return balance;
  } 

  public void setBalance(long balance) {
    this.balance = balance;
  } 

  @Override
  public String toString() {
    return "Account [id=" + id + ", balance=" + balance + "]";
  } 

}
package com.cdai.orm.hibernate.transaction; 

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration; 

import com.cdai.orm.hibernate.annotation.Account; 

public class DirtyRead { 

  public static void main(String[] args) { 

    final SessionFactory sessionFactory = new AnnotationConfiguration().
        addFile("hibernate/hibernate.cfg.xml").
        configure().
        addPackage("com.cdai.orm.hibernate.annotation").
        addAnnotatedClass(Account.class).
        buildSessionFactory(); 

    Thread t1 = new Thread() { 

      @Override
      public void run() {
        Session session1 = sessionFactory.openSession();
        Transaction tx1 = null;
        try {
          tx1 = session1.beginTransaction();
          System.out.println("T1 - Begin trasaction");
          Thread.sleep(500); 

          Account account = (Account)
              session1.get(Account.class, new Long(1));
          System.out.println("T1 - balance=" + account.getBalance());
          Thread.sleep(500); 

          account.setBalance(account.getBalance() + 100);
          System.out.println("T1 - Change balance:" + account.getBalance()); 

          tx1.commit();
          System.out.println("T1 - Commit transaction");
          Thread.sleep(500);
        }
        catch (Exception e) {
          e.printStackTrace();
          if (tx1 != null)
            tx1.rollback();
        }
        finally {
          session1.close();
        }
      } 

    }; 

    // 3.Run transaction 2
    Thread t2 = new Thread() { 

      @Override
      public void run() {
        Session session2 = sessionFactory.openSession();
        Transaction tx2 = null;
        try {
          tx2 = session2.beginTransaction();
          System.out.println("T2 - Begin trasaction");
          Thread.sleep(500); 

          Account account = (Account)
              session2.get(Account.class, new Long(1));
          System.out.println("T2 - balance=" + account.getBalance());
          Thread.sleep(500); 

          account.setBalance(account.getBalance() - 100);
          System.out.println("T2 - Change balance:" + account.getBalance()); 

          tx2.commit();
          System.out.println("T2 - Commit transaction");
          Thread.sleep(500);
        }
        catch (Exception e) {
          e.printStackTrace();
          if (tx2 != null)
            tx2.rollback();
        }
        finally {
          session2.close();
        }
      } 

    }; 

    t1.start();
    t2.start(); 

    while (t1.isAlive() || t2.isAlive()) {
      try {
        Thread.sleep(2000L);
      } catch (InterruptedException e) {
      }
    } 

    System.out.println("Both T1 and T2 are dead.");
    sessionFactory.close(); 

  } 

}

事务1将col_balance减小100,而事务2将其减少100,最终结果可能是0,也
可能是200,事务1或2的更新可能会丢失。log输出也印证了这一点,事务1和2
的log交叉打印。

T1 - Begin trasaction
T2 - Begin trasaction
Hibernate: select account0_.col_id as col1_0_0_, account0_.col_balance as col2_0_0_ from tb_account account0_ where account0_.col_id=?
Hibernate: select account0_.col_id as col1_0_0_, account0_.col_balance as col2_0_0_ from tb_account account0_ where account0_.col_id=?
T1 - balance=100
T2 - balance=100
T2 - Change balance:0
T1 - Change balance:200
Hibernate: update tb_account set col_balance=? where col_id=?
Hibernate: update tb_account set col_balance=? where col_id=?
T1 - Commit transaction
T2 - Commit transaction
Both T1 and T2 are dead.

由此可见,隔离性是一个需要慎重考虑的问题,理解锁很有必要。

二、有多少种锁?

常见的有共享锁、更新锁和独占锁。

1.共享锁:用于读数据操作,允许其他事务同时读取。当事务执行select语句时,
数据库自动为事务分配一把共享锁来锁定读取的数据。
2.独占锁:用于修改数据,其他事务不能读取也不能修改。当事务执行insert、
update和delete时,数据库会自动分配。
3.更新锁:用于避免更新操作时共享锁造成的死锁,比如事务1和2同时持有
共享锁并等待获得独占锁。当执行update时,事务先获得更新锁,然后将
更新锁升级成独占锁,这样就避免了死锁。

此外,这些锁都可以施加到数据库中不同的对象上,即这些锁可以有不同的粒度。
如数据库级锁、表级锁、页面级锁、键级锁和行级锁。

所以锁是有很多种的,这么多锁要想完全掌握灵活使用太难了,我们又不是DBA。
怎么办?还好,锁机制对于我们一般用户来说是透明的,数据库会自动添加合适的
锁,并在适当的时机自动升级、降级各种锁,真是太周到了!我们只需要做的就是
学会根据不同的业务需求,设置好隔离级别就可以了。

三、怎样设置隔离级别?

一般来说,数据库系统会提供四种事务隔离级别供用户选择:

1.Serializable(串行化):当两个事务同时操纵相同数据时,事务2只能停下来等。

2.Repeatable Read(可重复读):事务1能看到事务2新插入的数据,不能看到对
已有数据的更新。

3.Read Commited(读已提交数据):事务1能看到事务2新插入和更新的数据。

4.Read Uncommited(读未提交数据):事务1能看到事务2没有提交的插入和更新
数据。

四、应用程序中的锁

当数据库采用Read Commited隔离级别时,可以在应用程序中采用悲观锁或乐观锁。

1.悲观锁:假定当前事务操作的数据肯定还会有其他事务访问,因此悲观地在应用
程序中显式指定采用独占锁来锁定数据资源。在MySQL、Oracle中支持以下形式:

   select ... for update

显式地让select采用独占锁锁定查询的记录,其他事务要查询、更新或删除这些被
锁定的数据,都要等到该事务结束后才行。

在Hibernate中,可以在load时传入LockMode.UPGRADE来采用悲观锁。修改前面的例子,
在事务1和2的get方法调用处,多传入一个LockMode参数。从log中可以看出,事务1和2
不再是交叉运行,事务2等待事务1结束后才可以读取数据,所以最终col_balance值是正确
的100。

package com.cdai.orm.hibernate.transaction; 

import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction; 

import com.cdai.orm.hibernate.annotation.Account;
import com.cdai.orm.hibernate.annotation.AnnotationHibernate; 

public class UpgradeLock { 

  @SuppressWarnings("deprecation")
  public static void main(String[] args) { 

    final SessionFactory sessionFactory = AnnotationHibernate.createSessionFactory();  

    // Run transaction 1
    Thread t1 = new Thread() { 

      @Override
      public void run() {
        Session session1 = sessionFactory.openSession();
        Transaction tx1 = null;
        try {
          tx1 = session1.beginTransaction();
          System.out.println("T1 - Begin trasaction");
          Thread.sleep(500); 

          Account account = (Account)
              session1.get(Account.class, new Long(1), LockMode.UPGRADE);
          System.out.println("T1 - balance=" + account.getBalance());
          Thread.sleep(500); 

          account.setBalance(account.getBalance() + 100);
          System.out.println("T1 - Change balance:" + account.getBalance()); 

          tx1.commit();
          System.out.println("T1 - Commit transaction");
          Thread.sleep(500);
        }
        catch (Exception e) {
          e.printStackTrace();
          if (tx1 != null)
            tx1.rollback();
        }
        finally {
          session1.close();
        }
      } 

    }; 

    // Run transaction 2
    Thread t2 = new Thread() { 

      @Override
      public void run() {
        Session session2 = sessionFactory.openSession();
        Transaction tx2 = null;
        try {
          tx2 = session2.beginTransaction();
          System.out.println("T2 - Begin trasaction");
          Thread.sleep(500); 

          Account account = (Account)
              session2.get(Account.class, new Long(1), LockMode.UPGRADE);
          System.out.println("T2 - balance=" + account.getBalance());
          Thread.sleep(500); 

          account.setBalance(account.getBalance() - 100);
          System.out.println("T2 - Change balance:" + account.getBalance()); 

          tx2.commit();
          System.out.println("T2 - Commit transaction");
          Thread.sleep(500);
        }
        catch (Exception e) {
          e.printStackTrace();
          if (tx2 != null)
            tx2.rollback();
        }
        finally {
          session2.close();
        }
      } 

    }; 

    t1.start();
    t2.start(); 

    while (t1.isAlive() || t2.isAlive()) {
      try {
        Thread.sleep(2000L);
      } catch (InterruptedException e) {
      }
    } 

    System.out.println("Both T1 and T2 are dead.");
    sessionFactory.close(); 

  } 

}
T1 - Begin trasaction
T2 - Begin trasaction
Hibernate: select account0_.col_id as col1_0_0_, account0_.col_balance as col2_0_0_ from tb_account account0_ with (updlock, rowlock) where account0_.col_id=?
Hibernate: select account0_.col_id as col1_0_0_, account0_.col_balance as col2_0_0_ from tb_account account0_ with (updlock, rowlock) where account0_.col_id=?
T2 - balance=100
T2 - Change balance:0
Hibernate: update tb_account set col_balance=? where col_id=?
T2 - Commit transaction
T1 - balance=0
T1 - Change balance:100
Hibernate: update tb_account set col_balance=? where col_id=?
T1 - Commit transaction
Both T1 and T2 are dead.

Hibernate对于SQLServer 2005会执行SQL:

代码如下:

select account0_.col_id as col1_0_0_, account0_.col_balance as col2_0_0_ from tb_account account0_ with (updlock, rowlock) where account0_.col_id=?

为选定的col_id为1的数据行加上行锁和更新锁。

2.乐观锁:假定当前事务操作的数据不会有其他事务同时访问,因此完全依靠数据库
的隔离级别来自动管理锁的工作。在应用程序中采用版本控制来避免可能低概率出现
的并发问题。

在Hibernate中,使用Version注解来定义版本号字段。

将DirtyLock中的Account对象替换成AccountVersion,其他代码不变,执行出现异常。

package com.cdai.orm.hibernate.transaction; 

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Version; 

@Entity
@Table(name = "tb_account_version")
public class AccountVersion { 

  @Id
  @Column(name = "col_id")
  private long id; 

  @Column(name = "col_balance")
  private long balance; 

  @Version
  @Column(name = "col_version")
  private int version; 

  public AccountVersion() {
  } 

  public AccountVersion(long id, long balance) {
    this.id = id;
    this.balance = balance;
  } 

  public long getId() {
    return id;
  } 

  public void setId(long id) {
    this.id = id;
  } 

  public long getBalance() {
    return balance;
  } 

  public void setBalance(long balance) {
    this.balance = balance;
  } 

  public int getVersion() {
    return version;
  } 

  public void setVersion(int version) {
    this.version = version;
  } 

}

log如下:

T1 - Begin trasaction
T2 - Begin trasaction
Hibernate: select accountver0_.col_id as col1_0_0_, accountver0_.col_balance as col2_0_0_, accountver0_.col_version as col3_0_0_ from tb_account_version accountver0_ where accountver0_.col_id=?
Hibernate: select accountver0_.col_id as col1_0_0_, accountver0_.col_balance as col2_0_0_, accountver0_.col_version as col3_0_0_ from tb_account_version accountver0_ where accountver0_.col_id=?
T1 - balance=1000
T2 - balance=1000
T1 - Change balance:900
T2 - Change balance:1100
Hibernate: update tb_account_version set col_balance=?, col_version=? where col_id=? and col_version=?
Hibernate: update tb_account_version set col_balance=?, col_version=? where col_id=? and col_version=?
T1 - Commit transaction
2264 [Thread-2] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.cdai.orm.hibernate.transaction.AccountVersion#1]
   at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1934)
   at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2578)
   at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2478)
   at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2805)
   at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:114)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:260)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:180)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
   at com.cdai.orm.hibernate.transaction.VersionLock$2.run(VersionLock.java:93)
Both T1 and T2 are dead.

由于乐观锁完全将事务隔离交给数据库来控制,所以事务1和2交叉运行了,事务1提交
成功并将col_version改为1,然而事务2提交时已经找不到col_version为0的数据了,所以
抛出了异常。

Hibernate查询方法比较
Hibernate主要有三种查询方法:

1.HQL (Hibernate Query Language)

和SQL很类似,支持分页、连接、分组、聚集函数和子查询等特性,
但HQL是面向对象的,而不是面向关系数据库中的表。正因查询语句
是面向Domain对象的,所以使用HQL可以获得跨平台的好处,Hibernate
会自动帮我们根据不同的数据库翻译成不同的SQL语句。这在需要支持
多种数据库或者数据库迁移的应用中是十分方便的。

但得到方便的同时,由于SQL语句是由Hibernate自动生成的,所以这不
利于SQL语句的效率优化和调试,当数据量很大时可能会有效率问题,
出了问题也不便于排查解决。

2.QBC/QBE (Query by Criteria/Example)

QBC/QBE是通过组装查询条件或者模板对象来执行查询的。这在需要
灵活地支持许多查询条件自由组合的应用中是比较方便的。同样的问题
是由于查询语句是自由组装的,创建一条语句的代码可能很长,并且
包含许多分支条件,很不便于优化和调试。

3.SQL

Hibernate也支持直接执行SQL的查询方式。这种方式牺牲了Hibernate跨
数据库的优点,手工地编写底层SQL语句,从而获得最好的执行效率,
相对前两种方法,优化和调试方便了一些。

下面来看一组简单的例子。

package com.cdai.orm.hibernate.query; 

import java.util.Arrays;
import java.util.List; 

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Expression; 

import com.cdai.orm.hibernate.annotation.Account; 

public class BasicQuery { 

  public static void main(String[] args) { 

    SessionFactory sessionFactory = new AnnotationConfiguration().
                      addFile("hibernate/hibernate.cfg.xml").
                      configure().
                      addPackage("com.cdai.orm.hibernate.annotation").
                      addAnnotatedClass(Account.class).
                      buildSessionFactory(); 

    Session session = sessionFactory.openSession(); 

    // 1.HQL
    Query query = session.createQuery("from Account as a where a.id=:id");
    query.setLong("id", 1);
    List result = query.list();
    for (Object row : result) {
      System.out.println(row);
    } 

    // 2.QBC
    Criteria criteria = session.createCriteria(Account.class);
    criteria.add(Expression.eq("id", new Long(2)));
    result = criteria.list();
    for (Object row : result) {
      System.out.println(row);
    } 

    // 3.QBE
    Account example= new Account();
    example.setBalance(100);
    result = session.createCriteria(Account.class).
            add(Example.create(example)).
            list();
    for (Object row : result) {
      System.out.println(row);
    } 

    // 4.SQL
    query = session.createSQLQuery(
        " select top 10 * from tb_account order by col_id desc ");
    result = query.list();
    for (Object row : result) {
      System.out.println(Arrays.toString((Object[]) row));
  } 

    session.close();
  } 

}
Hibernate: select account0_.col_id as col1_0_, account0_.col_balance as col2_0_ from tb_account account0_ where account0_.col_id=?
Account [id=1, balance=100]
Hibernate: select this_.col_id as col1_0_0_, this_.col_balance as col2_0_0_ from tb_account this_ where this_.col_id=?
Account [id=2, balance=100]
Hibernate: select this_.col_id as col1_0_0_, this_.col_balance as col2_0_0_ from tb_account this_ where (this_.col_balance=?)
Account [id=1, balance=100]
Account [id=2, balance=100]
Hibernate: select top 10 * from tb_account order by col_id desc
[2, 100]
[1, 100]

从log中可以清楚的看到Hibernate对于生成的SQL语句的控制,具体选择
哪种查询方式就要看具体应用了。

(0)

相关推荐

  • Hibernate通用数据库操作代码

    insert方法 复制代码 代码如下: public void insert(Object o){Session session = HibernateSessionFactory.currentSession();Transaction t = session.beginTransaction();session.save(o);t.commit();HibernateSessionFactory.clossSession();} delete方法 复制代码 代码如下: public void

  • Hibernate对数据库删除、查找、更新操作实例代码

    本节继续hibernate对数据库的其他操作,删除.查询.修改. Hibernate对数据删除操作 删除User表中个一条数据,是需要更具User表的主键id值来删除的.首先根据id值向数据库中查询出来对应的对象.可以采用两种方式一是session的get方法,一个是session的load方法. Session的Get方法:调用这个方法会返回一个Object对象.然后我们对其强制转换.Useruser = (User)session.get(User.class," 402881e5441c0

  • Java的Hibernate框架中用于操作数据库的HQL语句讲解

    上次我们一起学习了用Criteria进行相关的操作,但由于Criteria并不是Hibernate官方推荐的查询方式,我们也并不多用.现在我们来看一下官方推荐的HQL,一起学习一下它的强大.  说是HQL,也就是Hibernate查询语句,和SQL有什么区别呢?一个字母的区别,哈哈.  当然不是这样,HQL和SQL的区别在于思想的不同,HQL是用面向对象的方向进行查询,而SQL则是对数据库二维表进行查询,这里包含的是思想的不同.HQL实际上也是SQL,它由Hibernate帮我们在内部进行转换,

  • Java Hibernate中使用HQL语句进行数据库查询的要点解析

    一.实体对象查询 实体对象查询是hql查询的基础,作为一种对象查询语言,在查询操作时和sql不同,查询字符串中的内容要使用类名和类的属性名来代替.这种查询方法相对简单,只要有SQL功底,使用hql是很简单的,但是有一些问题需要注意,就是查询获取数据不是目的,需要考虑的是如何编写出高效的查询语句,这才是讨论的重点. 1.N+1问题 (1)什么是N+1问题 在刚听到这个名词时疑惑可能是有的,以前根本就没有听过N+1问题,那么它是指什么呢?N+1指的是一张表中有N条数据,那么在获取这N条数据时会产生N

  • 扩展Hibernate使用自定义数据库连接池的方法

    本文实例讲述了扩展Hibernate使用自定义数据库连接池的方法.分享给大家供大家参考,具体如下: 在Hibernate的过程中往往碰到这样的问题:我们现成的产品本来已使用自有的数据库连接池,同时使用Hibernate的话在Hibernate配置中也得配置数据库连接信息,这样就需要在两个地方维护数据库连接信息,维护起来感觉相当别扭. 由于我们不是在产品刚开始开发就加入Hibernate的,所以不合适让产品直接使用Hibernate的连接池,只好让Hibernate来使用产品自有的连接池,还好Hi

  • 在Java的Hibernate框架中对数据库数据进行查询操作

    Hibernate查询语言(HQL)是一种面向对象的查询语言,类似于SQL,但不是对表和列操作,HQL适用于持久对象和它们的属性. HQL查询由Hibernate转换成传统的SQL查询,这在圈上的数据库执行操作. 虽然可以直接使用SQL语句和Hibernate使用原生SQL,但建议使用HQL尽可能避免数据库可移植性的麻烦,并采取Hibernate的SQL生成和缓存策略的优势. 都像SELECT,FROM和WHERE等关键字不区分大小写,但如表名和列名的属性是区分在HQL敏感. FROM 语句 使

  • 解决hibernate+mysql写入数据库乱码

    hibernate.cfg.xml加上属性. <property name="connection.useUnicode">true</property> <property name="connection.characterEncoding">UTF-8</property> mysql 的驱动用3.0.15以上版本的, 加个Filter, 使用UTF-8字符集就可以了, 若使用Spring则写在spring中的s

  • Java的Hibernate框架数据库操作中锁的使用和查询类型

     Hibernate与数据库锁 一.为什么要使用锁? 要想弄清楚锁机制存在的原因,首先要了解事务的概念. 事务是对数据库一系列相关的操作,它必须具备ACID特征: A(原子性):要么全部成功,要么全部撤销. C(一致性):要保持数据库的一致性. I(隔离性):不同事务操作相同数据时,要有各自的数据空间. D(持久性):一旦事务成功结束,它对数据库所做的更新必须永久保持. 我们常用的关系型数据库RDBMS实现了事务的这些特性.其中,原子性. 一致性和持久性都是采用日志来保证的.而隔离性就是由今天我

  • 简介Java的Hibernate框架中的Session和持久化类

    Session Session对象用于获取与数据库的物理连接. Session对象是重量轻,设计了一个互动是需要与数据库每次被实例化.持久化对象被保存,并通过一个Session对象中检索. 会话中的对象不应该保持开放很长一段时间,因为他们通常不被线程安全的,他们应该被创建并根据需要摧毁他们.这次会议的主要功能是提供创建,读取和删除操作映射的实体类的实例.实例中可能存在以下三种状态之一在给定时间点: 短暂性: 持久化类的未与会话相关联,并在数据库中没有代表性,没有标识值的新实例被Hibernate

  • 深入解析Java的Hibernate框架中的持久对象

    一.持久对象生命周期 应用程序在使用Hibernate框架后,创建的持久对象会经历一整套生命周期来完成数据库的操作,其中主要的三个状态分别是瞬态(Transient).持久化(Persistent).脱管(detached).这三种状态的转换是能够在应用程序中控制的,如下图: 为了能清楚的了解这几种状态,这里使用一个实例来查看下这几种状态下对象的不同,下面状态内的代码,具体步骤如下: (1)创建Hibernate_session程序集,并添加像相应的jar包: (2)配置Hibernate,添加

  • 解析Java的Hibernate框架中的持久化类和映射文件

    持久化类 Hibernate的整个概念是采取从Java类属性的值,并将持久到数据库表.一个映射文件Hibernate的帮助确定如何从拉动类的值,并将它们映射与表和相关的域. 其对象或实例将存储在数据库表中的Java类在Hibernate中称为持久化类. Hibernate的效果最好,如果这些类遵循一些简单的规则,也称为普通Java对象(POJO)编程模型.有下列持久化类的主要规则,但是,这些规则并不是必需的. 将所有的持久化Java类需要一个默认的构造函数. 所有类应该包含为了让容易识别对象内H

  • 详解Java的Hibernate框架中的缓存与二级缓存

    缓存 今天我们就来讲一下hibernate中实体状态和hibernate缓存.  1)首先我们先来看一下实体状态:  实体状态主要分三种:transient,persitent,detached.  看英文应该就大概明白了吧.  transient:是指数据还没跟数据库中的数据相对应.  persistent:是指数据跟数据库中的数据相对应,它的任何改变都会反映到数据库中.  detached:是指数据跟数据库中的数据相对应,但由于session被关闭,它所做的修改不会对数据库的记录造成影响.

  • 详解Java的Hibernate框架中的缓存与原生SQL语句的使用

    Hibernate缓存 缓存是所有关于应用程序的性能优化和它位于应用程序和数据库之间,以避免数据库访问多次,让性能关键型应用程序有更好的表现. 缓存对Hibernate很重要,它采用了多级缓存方案下文所述: 第一级缓存: 第一级缓存是Session的缓存,是一个强制性的缓存,通过它所有的请求都必须通过. Session对象不断自身的动力的对象,提交到数据库之前. 如果发出多个更新一个对象,Hibernate试图拖延尽可能长的时间做了更新,以减少发出的更新SQL语句的数量.如果您关闭会话,所有被缓

  • Java的Hibernate框架结合MySQL的入门学习教程

    零.关于Hibernate Hibernate是冬眠的意思,它是指动物的冬眠,但是本文讨论的Hibernate却与冬眠毫无关系,而是接下来要讨论的SSH2框架中的一员.Hibernate是一个开源的项目,它是一个对象关系模型的框架,并且对JDBC进行了非常轻量级的封装,程序员在开发时可以使用对象编程思维进行开发. 下载地址:http://hibernate.org/orm/downloads/ Note:轻量级和重量级的区别,轻量级的框架包较小,并且使用较简单,而且测试容易,开发效率高:重量级框

  • 简要分析Java的Hibernate框架中的自定义类型

    最近看到hibernate的自定义类型,这个以前没接触过,在这里记录一下,当是对自己知识的巩固,也让没有接触过的朋友一起学习研究一番.  1)自定义类型,顾名思义,当然就是由于内部的类型不满足需求,而自己来进行实现的类型.这种情况不多,但我们还是有必要学习一下,技多不压身嘛.也学习一下,别人在做框架的时候是怎么去考虑的,怎么去思考扩展性的.  自定义类型有两个方法来实现,一种是实现UserType,另外一种实现CompositeUserType,另外可能还有一些方法,但我暂时没用到,先不讲了.

随机推荐