国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

詳解Java的Hibernate框架中的緩存與原生SQL語句的使用

2019-11-26 14:44:01
字體:
供稿:網(wǎng)友

Hibernate緩存
緩存是所有關(guān)于應(yīng)用程序的性能優(yōu)化和它位于應(yīng)用程序和數(shù)據(jù)庫之間,以避免數(shù)據(jù)庫訪問多次,讓性能關(guān)鍵型應(yīng)用程序有更好的表現(xiàn)。

緩存對Hibernate很重要,它采用了多級緩存方案下文所述:

2015122384816664.jpg (476×363)

第一級緩存:
第一級緩存是Session的緩存,是一個強(qiáng)制性的緩存,通過它所有的請求都必須通過。 Session對象不斷自身的動力的對象,提交到數(shù)據(jù)庫之前。

如果發(fā)出多個更新一個對象,Hibernate試圖拖延盡可能長的時間做了更新,以減少發(fā)出的更新SQL語句的數(shù)量。如果您關(guān)閉會話,所有被緩存的對象都將丟失,要么持久,或在數(shù)據(jù)庫中更新。

二級緩存:
二級緩存是可選的緩存和一級緩存,總是會征詢?nèi)魏卧噲D找到一個對象的二級緩存之前。第二級緩存可以在每個類和每個集合基礎(chǔ)上進(jìn)行配置,主要負(fù)責(zé)在會話緩存的對象。

任何第三方緩存可以使用Hibernate。org.hibernate.cache.CacheProvider接口提供,必須實(shí)施提供Hibernate一個句柄緩存實(shí)現(xiàn)。

查詢級別緩存:
Hibernate也實(shí)現(xiàn)了查詢結(jié)果集緩存與二級緩存的緊密集成在一起。

這是一個可選功能,需要兩個額外的物理緩存中保存緩存的查詢結(jié)果和地區(qū)當(dāng)一個表的最后更新的時間戳。這只是針對那些使用相同的參數(shù)經(jīng)常運(yùn)行的查詢非常有用。

二級緩存:
Hibernate使用一級緩存,默認(rèn)情況下,你什么都沒有做使用第一級緩存。讓我們直接進(jìn)入可選的第二級緩存。并不是所有的類受益于緩存,這樣一來就能禁用二級緩存是很重要的

Hibernate二級緩存被設(shè)置為兩個步驟。首先,必須決定要使用的并發(fā)策略。在此之后,可以配置緩存過期和使用緩存提供物理緩存屬性。

并發(fā)策略:
并發(fā)策略是一個中介的負(fù)責(zé)存儲數(shù)據(jù)項在緩存并從緩存中檢索它們。如果要啟用二級緩存,將必須決定,為每個持久化類和集合,要使用的緩存并發(fā)策略。

Transactional: 使用這種策略的主要讀取數(shù)據(jù)的地方,以防止過時的數(shù)據(jù)的并發(fā)事務(wù),在更新的罕見情況下是至關(guān)重要的。

Read-write: 再次使用這種策略的主要讀取數(shù)據(jù)的地方,以防止并發(fā)事務(wù)陳舊的數(shù)據(jù)是至關(guān)重要的,在更新的罕見情況。

Nonstrict-read-write: 這種策略不保證緩存與數(shù)據(jù)庫之間的一致性。使用此策略,如果數(shù)據(jù)很少改變和陳舊數(shù)據(jù)的可能性很小關(guān)鍵是不關(guān)注。

Read-only: 并發(fā)策略適用于數(shù)據(jù),永遠(yuǎn)不會改變。使用數(shù)據(jù)僅供參考。

如果我們要使用第二級緩存為我們的Employee類,讓我們添加告訴Hibernate使用可讀寫的高速緩存策略Employee實(shí)例所需的映射元素。

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC  "-//Hibernate/Hibernate Mapping DTD//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping>  <class name="Employee" table="EMPLOYEE">   <meta attribute="class-description">     This class contains the employee detail.    </meta>   <cache usage="read-write"/>   <id name="id" type="int" column="id">     <generator class="native"/>   </id>   <property name="firstName" column="first_name" type="string"/>   <property name="lastName" column="last_name" type="string"/>   <property name="salary" column="salary" type="int"/>  </class></hibernate-mapping>

 usage="read-write" 屬性告訴Hibernate使用一個可讀寫的并發(fā)策略定義的緩存。

緩存提供者:
考慮到會用你的緩存候選類的并發(fā)策略后,下一步就是選擇一個緩存提供程序。Hibernate迫使選擇一個緩存提供整個應(yīng)用程序。

2015122384847796.png (652×514)

在指定hibernate.cfg.xml配置文件中的緩存提供。選擇EHCache作為第二級緩存提供程序:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration>  <session-factory>  <property name="hibernate.dialect">   org.hibernate.dialect.MySQLDialect  </property>  <property name="hibernate.connection.driver_class">   com.mysql.jdbc.Driver  </property>  <!-- Assume students is the database name -->  <property name="hibernate.connection.url">   jdbc:mysql://localhost/test  </property>  <property name="hibernate.connection.username">   root  </property>  <property name="hibernate.connection.password">   root123  </property>  <property name="hibernate.cache.provider_class">   org.hibernate.cache.EhCacheProvider  </property>  <!-- List of XML mapping files -->  <mapping resource="Employee.hbm.xml"/></session-factory></hibernate-configuration>

現(xiàn)在,需要指定緩存區(qū)域的屬性。EHCache都有自己的配置文件ehcache.xml,在應(yīng)用程序在CLASSPATH中。在ehcache.xml中Employee類高速緩存配置可能看起來像這樣:

<diskStore path="java.io.tmpdir"/><defaultCachemaxElementsInMemory="1000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="true"/><cache name="Employee"maxElementsInMemory="500"eternal="true"timeToIdleSeconds="0"timeToLiveSeconds="0"overflowToDisk="false"/>

就這樣,現(xiàn)在啟用Employee類的二級緩存和Hibernate現(xiàn)在二級緩存,每當(dāng)瀏覽到一個雇員或當(dāng)通過標(biāo)識符加載雇員。

應(yīng)該分析你所有的類,并選擇適當(dāng)?shù)木彺娌呗詾槊總€類。有時,二級緩存可能降級的應(yīng)用程序的性能。所以建議到基準(zhǔn)應(yīng)用程序第一次沒有啟用緩存,非常適合緩存和檢查性能。如果緩存不提高系統(tǒng)性能再有就是在使任何類型的緩存是沒有意義的。

查詢級別緩存:
使用查詢緩存,必須先使用 hibernate.cache.use_query_cache="true"屬性配置文件中激活它。如果將此屬性設(shè)置為true,讓Hibernate的在內(nèi)存中創(chuàng)建所需的高速緩存來保存查詢和標(biāo)識符集。

接下來,使用查詢緩存,可以使用Query類的setCacheable(Boolean)方法。例如:

Session session = SessionFactory.openSession();Query query = session.createQuery("FROM EMPLOYEE");query.setCacheable(true);List users = query.list();SessionFactory.closeSession();

Hibernate也支持通過一個緩存區(qū)域的概念非常細(xì)粒度的緩存支持。緩存區(qū)是這是給定一個名稱緩存的一部分。

Session session = SessionFactory.openSession();Query query = session.createQuery("FROM EMPLOYEE");query.setCacheable(true);query.setCacheRegion("employee");List users = query.list();SessionFactory.closeSession();

此代碼使用方法告訴Hibernate來存儲和查找在緩存中的員工方面的查詢。


Hibernate原生SQL
可以使用原生SQL來表達(dá)數(shù)據(jù)庫查詢,如果想利用數(shù)據(jù)庫特有的功能,如查詢提示或者Oracle中的CONNECT關(guān)鍵字。 Hibernate3.x允許使用手寫SQL語句,包括存儲過程,所有的創(chuàng)建,更新,刪除和load操作。

應(yīng)用程序?qū)臅拕?chuàng)建一個原生SQL查詢(Session接口上)createSQLQuery()方法:

public SQLQuery createSQLQuery(String sqlString) throws HibernateException
當(dāng)傳遞一個包含SQL查詢到createSQLQuery()方法,可以將SQL結(jié)果與任何現(xiàn)有的Hibernate實(shí)體,聯(lián)接,或者一個標(biāo)量結(jié)果使用addEntity()方法,addJoin(),和addScalar()方法關(guān)聯(lián)的字符串。

標(biāo)量查詢:
最基本的SQL查詢是從一個或多個表中得到標(biāo)量(數(shù)值)的列表。以下是語法使用原生SQL標(biāo)量的值:

String sql = "SELECT first_name, salary FROM EMPLOYEE";SQLQuery query = session.createSQLQuery(sql);query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);List results = query.list();

實(shí)體的查詢:
上面的查詢都是返回標(biāo)量值,也就是從resultset中返回的“裸”數(shù)據(jù)。以下是語法通過addEntity()方法來從原生SQL查詢獲得實(shí)體對象作為一個整體。

String sql = "SELECT * FROM EMPLOYEE";SQLQuery query = session.createSQLQuery(sql);query.addEntity(Employee.class);List results = query.list();

命名SQL查詢:
以下是語法通過addEntity()方法來從原生SQL查詢獲得實(shí)體對象和使用命名SQL查詢。

String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";SQLQuery query = session.createSQLQuery(sql);query.addEntity(Employee.class);query.setParameter("employee_id", 10);List results = query.list();

Native SQL 例子:
考慮下面的POJO類:

public class Employee {  private int id;  private String firstName;   private String lastName;    private int salary;   public Employee() {}  public Employee(String fname, String lname, int salary) {   this.firstName = fname;   this.lastName = lname;   this.salary = salary;  }  public int getId() {   return id;  }  public void setId( int id ) {   this.id = id;  }  public String getFirstName() {   return firstName;  }  public void setFirstName( String first_name ) {   this.firstName = first_name;  }  public String getLastName() {   return lastName;  }  public void setLastName( String last_name ) {   this.lastName = last_name;  }  public int getSalary() {   return salary;  }  public void setSalary( int salary ) {   this.salary = salary;  }}

讓我們創(chuàng)建下面的EMPLOYEE表來存儲Employee對象:

create table EMPLOYEE (  id INT NOT NULL auto_increment,  first_name VARCHAR(20) default NULL,  last_name VARCHAR(20) default NULL,  salary   INT default NULL,  PRIMARY KEY (id));

以下將被映射文件。

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC  "-//Hibernate/Hibernate Mapping DTD//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping>  <class name="Employee" table="EMPLOYEE">   <meta attribute="class-description">     This class contains the employee detail.    </meta>   <id name="id" type="int" column="id">     <generator class="native"/>   </id>   <property name="firstName" column="first_name" type="string"/>   <property name="lastName" column="last_name" type="string"/>   <property name="salary" column="salary" type="int"/>  </class></hibernate-mapping>

最后,我們將創(chuàng)建應(yīng)用程序類的main()方法來運(yùn)行,我們將使用原生SQL查詢的應(yīng)用程序:

import java.util.*;  import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction;import org.hibernate.SessionFactory;import org.hibernate.SQLQuery;import org.hibernate.Criteria;import org.hibernate.Hibernate;import org.hibernate.cfg.Configuration;public class ManageEmployee {  private static SessionFactory factory;   public static void main(String[] args) {   try{     factory = new Configuration().configure().buildSessionFactory();   }catch (Throwable ex) {      System.err.println("Failed to create sessionFactory object." + ex);     throw new ExceptionInInitializerError(ex);    }   ManageEmployee ME = new ManageEmployee();   /* Add few employee records in database */   Integer empID1 = ME.addEmployee("Zara", "Ali", 2000);   Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);   Integer empID3 = ME.addEmployee("John", "Paul", 5000);   Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000);   /* List down employees and their salary using Scalar Query */   ME.listEmployeesScalar();   /* List down complete employees information using Entity Query */   ME.listEmployeesEntity();  }  /* Method to CREATE an employee in the database */  public Integer addEmployee(String fname, String lname, int salary){   Session session = factory.openSession();   Transaction tx = null;   Integer employeeID = null;   try{     tx = session.beginTransaction();     Employee employee = new Employee(fname, lname, salary);     employeeID = (Integer) session.save(employee);      tx.commit();   }catch (HibernateException e) {     if (tx!=null) tx.rollback();     e.printStackTrace();    }finally {     session.close();    }   return employeeID;  }  /* Method to READ all the employees using Scalar Query */  public void listEmployeesScalar( ){   Session session = factory.openSession();   Transaction tx = null;   try{     tx = session.beginTransaction();     String sql = "SELECT first_name, salary FROM EMPLOYEE";     SQLQuery query = session.createSQLQuery(sql);     query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);     List data = query.list();     for(Object object : data)     {      Map row = (Map)object;      System.out.print("First Name: " + row.get("first_name"));       System.out.println(", Salary: " + row.get("salary"));      }     tx.commit();   }catch (HibernateException e) {     if (tx!=null) tx.rollback();     e.printStackTrace();    }finally {     session.close();    }  }  /* Method to READ all the employees using Entity Query */  public void listEmployeesEntity( ){   Session session = factory.openSession();   Transaction tx = null;   try{     tx = session.beginTransaction();     String sql = "SELECT * FROM EMPLOYEE";     SQLQuery query = session.createSQLQuery(sql);     query.addEntity(Employee.class);     List employees = query.list();     for (Iterator iterator =               employees.iterator(); iterator.hasNext();){      Employee employee = (Employee) iterator.next();       System.out.print("First Name: " + employee.getFirstName());       System.out.print(" Last Name: " + employee.getLastName());       System.out.println(" Salary: " + employee.getSalary());      }     tx.commit();   }catch (HibernateException e) {     if (tx!=null) tx.rollback();     e.printStackTrace();    }finally {     session.close();    }  }}

編譯和執(zhí)行:
下面是步驟來編譯并運(yùn)行上述應(yīng)用程序。請確保在進(jìn)行的編譯和執(zhí)行之前,適當(dāng)?shù)卦O(shè)置PATH和CLASSPATH。

執(zhí)行ManageEmployee二進(jìn)制文件來運(yùn)行程序。

會得到以下結(jié)果,并記錄將在EMPLOYEE表中創(chuàng)建。

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........First Name: Zara, Salary: 2000First Name: Daisy, Salary: 5000First Name: John, Salary: 5000First Name: Mohd, Salary: 3000First Name: Zara Last Name: Ali Salary: 2000First Name: Daisy Last Name: Das Salary: 5000First Name: John Last Name: Paul Salary: 5000First Name: Mohd Last Name: Yasee Salary: 3000

如果檢查EMPLOYEE表,它應(yīng)該記錄下已:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+| id | first_name | last_name | salary |+----+------------+-----------+--------+| 26 | Zara    | Ali    |  2000 || 27 | Daisy   | Das    |  5000 || 28 | John    | Paul   |  5000 || 29 | Mohd    | Yasee   |  3000 |+----+------------+-----------+--------+4 rows in set (0.00 sec)
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 宁河县| 犍为县| 綦江县| 亳州市| 神农架林区| 襄樊市| 合肥市| 渭南市| 邯郸市| 辽宁省| 称多县| 潼南县| 遂溪县| 高州市| 兰溪市| 古交市| 古浪县| 万宁市| 嘉祥县| 藁城市| 惠安县| 三亚市| 洱源县| 巴林右旗| 沂南县| 海南省| 双流县| 柯坪县| 民丰县| 彩票| 北辰区| 综艺| 怀安县| 泰顺县| 海安县| 临夏市| 奉贤区| 普宁市| 洛隆县| 九龙城区| 阿拉善右旗|