Maison >Java >javaDidacticiel >Explication détaillée des annotations et de la mise en cache dans le framework Hibernate de Java

Explication détaillée des annotations et de la mise en cache dans le framework Hibernate de Java

高洛峰
高洛峰original
2017-01-23 11:53:301239parcourir

Annotations
Les annotations Hibernate sont une nouvelle façon de définir des mappages sans utiliser de fichiers XML. Vous pouvez utiliser des annotations en plus ou en remplacement des métadonnées de mappage XML.

Les annotations Hibernate sont un moyen puissant de fournir un mappage entre les objets de métadonnées et les tables relationnelles. Toutes les métadonnées sont regroupées dans le code du fichier java POJO, ce qui aide l'utilisateur à comprendre à la fois la structure de la table et le POJO pendant le processus de développement.

Si vous envisagez de porter votre application vers d'autres applications ORM de spécification EJB3, vous devez utiliser des annotations pour exprimer les informations de mappage, mais si vous souhaitez une plus grande flexibilité, vous devez utiliser un mappage basé sur XML.

Paramètres d'environnement Hiberner les annotations
Tout d'abord, vous devez vous assurer que vous utilisez JDK5.0, sinon vous devez mettre à niveau le JDK vers JDK5.0 pour profiter de la prise en charge native des annotations.

Deuxièmement, vous devez installer le package de distribution d'annotations Hibernate 3.x, qui peut être obtenu auprès de SourceForge : (Télécharger Hibernate Annotation) et copier hibernate-annotations.jar, lib/hibernate-comons-annotations.jar. et lib/ejb3 -persistence.jar Attribuer une instance de classe de l'annotation Hibernate à CLASSPATH

annotation :
Comme mentionné lors de l'utilisation de l'annotation Hibernate, travaillez toutes les métadonnées dans le fichier java POJO avec le code ci-dessus, cela peut aider les utilisateurs comprennent la structure de la table et POJO en même temps pendant le processus de développement.

Considérez les objets qui seront stockés à l'aide de la table EMPLOYEE suivante :

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)
);

Ce qui suit sont les annotations utilisées pour mapper et définir l'objet Classe Employee de l'EMPLOYÉ Mappage de table :

import javax.persistence.*;
 
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
  @Id @GeneratedValue
  @Column(name = "id")
  private int id;
 
  @Column(name = "first_name")
  private String firstName;
 
  @Column(name = "last_name")
  private String lastName;
 
  @Column(name = "salary")
  private int salary;
 
  public Employee() {}
  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;
  }
}

Hibernate détecte que l'annotation @Id se trouve sur un champ et suppose qu'elle doit être accessible directement via le domaine d'exécution en tant que propriété d'un objet. Si vous annotez la méthode getId() avec @Id, l'accès à la propriété sera autorisé par défaut via les méthodes getter et setter. Par conséquent, toutes les autres annotations sont également placées sur la méthode field ou getter, en suivant la stratégie sélectionnée. La section suivante expliquera les annotations utilisées dans la classe ci-dessus.

@Entity Remarque :
La spécification EJB3 est incluse dans le package javax.persistence, nous importons donc ce package dans un premier temps. Deuxièmement, nous avons utilisé l'annotation @Entity pour marquer cette classe comme classe Employee du bean entité, elle doit donc avoir un constructeur sans paramètre qui est enfin visible dans une portée protégée.

Annotation @Table : L'annotation
@Table permet d'utiliser la table spécifiée pour enregistrer les détails de cette entité dans la base de données.

L'annotation @Table fournit quatre propriétés qui permettent de remplacer le nom de la table, son répertoire, son schéma et d'appliquer des contraintes uniques sur les colonnes de la table. Nous utilisons maintenant le nom de la table EMPLOYEE qui vient d'être donné.

Annotations @Id et @GeneratedValue :
Chaque bean entité aura une clé primaire annotée dans l'annotation @Id de la classe. La clé primaire peut être un champ unique ou une combinaison de plusieurs champs selon la structure de la table.

Par défaut, l'annotation @Id détermine automatiquement la stratégie de génération de clé primaire la plus appropriée à utiliser, mais cela peut être réalisé en appliquant l'annotation @GeneratedValue, qui accepte deux paramètres, stratégie et générateur, qui ne sont pas prévus à discuter ici. Utilisez simplement la politique de génération de clé par défaut. Laisser Hibernate déterminer le type de générateur à utiliser rend le code portable entre différentes bases de données.

Annotation @Column : L'annotation
@Column est utilisée pour spécifier les détails d'une colonne à laquelle un champ ou un attribut sera mappé. Les attributs suivants les plus couramment utilisés peuvent être utilisés avec les annotations de colonne :

L'attribut

name permet de spécifier explicitement le nom de la colonne. L'attribut

length permet d'utiliser la taille d'une colonne pour mapper une valeur, en particulier une valeur de chaîne. L'attribut

nullable permet à la colonne d'être marquée NOT NULL lors de la génération du schéma. L'attribut

unique permet de marquer les colonnes comme contenant uniquement des valeurs uniques.

Créer la classe d'application :
Enfin, nous créerons la méthode main() de la classe d'application pour exécuter l'application. Nous utiliserons cette application pour sauvegarder certains enregistrements d'employés, puis nous appliquerons des opérations CRUD sur les enregistrements.

import java.util.List;
import java.util.Date;
import java.util.Iterator;
  
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
 
public class ManageEmployee {
  private static SessionFactory factory;
  public static void main(String[] args) {
   try{
     factory = new AnnotationConfiguration().
          configure().
          //addPackage("com.xyz") //add package if used.
          addAnnotatedClass(Employee.class).
          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", 1000);
   Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
   Integer empID3 = ME.addEmployee("John", "Paul", 10000);
 
   /* List down all the employees */
   ME.listEmployees();
 
   /* Update employee's records */
   ME.updateEmployee(empID1, 5000);
 
   /* Delete an employee from the database */
   ME.deleteEmployee(empID2);
 
   /* List down new list of the employees */
   ME.listEmployees();
  }
  /* 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();
     employee.setFirstName(fname);
     employee.setLastName(lname);
     employee.setSalary(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 */
  public void listEmployees( ){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     List employees = session.createQuery("FROM Employee").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();
   }
  }
  /* Method to UPDATE salary for an employee */
  public void updateEmployee(Integer EmployeeID, int salary ){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     Employee employee =
          (Employee)session.get(Employee.class, EmployeeID);
     employee.setSalary( salary );
  session.update(employee);
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace();
   }finally {
     session.close();
   }
  }
  /* Method to DELETE an employee from the records */
  public void deleteEmployee(Integer EmployeeID){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     Employee employee =
          (Employee)session.get(Employee.class, EmployeeID);
     session.delete(employee);
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace();
   }finally {
     session.close();
   }
  }
}

Configuration de la base de données :
Maintenant, créons le fichier de configuration hibernate.cfg.xml pour définir les paramètres pertinents de la base de données.

<?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">
   cohondob
  </property>
 
</session-factory>
</hibernate-configuration>

Compiler et exécuter :
Vous trouverez ci-dessous les étapes pour compiler et exécuter l'application ci-dessus. Veuillez vous assurer que PATH et CLASSPATH sont définis correctement avant la compilation et l'exécution.

Supprimez le fichier de mappage Employee.hbm.xml du chemin.

Créez le fichier source Employee.java comme indiqué ci-dessus et compilez-le.

Créez le fichier source ManageEmployee.java comme indiqué ci-dessus et compilez-le.

Exécutez le binaire ManageEmployee pour exécuter le programme.

obtiendra les résultats suivants et les enregistrements seront dans la table EMPLOYÉ.

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
 
First Name: Zara Last Name: Ali Salary: 1000
First Name: Daisy Last Name: Das Salary: 5000
First Name: John Last Name: Paul Salary: 10000
First Name: Zara Last Name: Ali Salary: 5000
First Name: John Last Name: Paul Salary: 10000

Si vous vérifiez la table EMPLOYEE, elle devrait contenir les enregistrements suivants :

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara    | Ali    |  5000 |
| 31 | John    | Paul   | 10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec
 
mysql>

Mise en cache
La mise en cache concerne l'optimisation des performances des applications et il est situé entre l'application et la base de données pour éviter les accès multiples à la base de données et permettre aux applications critiques en termes de performances de mieux fonctionner.

La mise en cache est très importante pour Hibernate, qui utilise un schéma de mise en cache à plusieurs niveaux comme décrit ci-dessous :

Explication détaillée des annotations et de la mise en cache dans le framework Hibernate de Java

第一级缓存:
第一级缓存是Session的缓存,是一个强制性的缓存,通过它所有的请求都必须通过。 Session对象不断自身的动力的对象,提交到数据库之前。

如果发出多个更新一个对象,Hibernate试图拖延尽可能长的时间做了更新,以减少发出的更新SQL语句的数量。如果您关闭会话,所有被缓存的对象都将丢失,要么持久,或在数据库中更新。

二级缓存:
二级缓存是可选的缓存和一级缓存,总是会征询任何试图找到一个对象的二级缓存之前。第二级缓存可以在每个类和每个集合基础上进行配置,主要负责在会话缓存的对象。

任何第三方缓存可以使用Hibernate。org.hibernate.cache.CacheProvider接口提供,必须实施提供Hibernate一个句柄缓存实现。

查询级别缓存:
Hibernate也实现了查询结果集缓存与二级缓存的紧密集成在一起。

这是一个可选功能,需要两个额外的物理缓存中保存缓存的查询结果和地区当一个表的最后更新的时间戳。这只是针对那些使用相同的参数经常运行的查询非常有用。

二级缓存:
Hibernate使用一级缓存,默认情况下,你什么都没有做使用第一级缓存。让我们直接进入可选的第二级缓存。并不是所有的类受益于缓存,这样一来就能禁用二级缓存是很重要的

Hibernate二级缓存被设置为两个步骤。首先,必须决定要使用的并发策略。在此之后,可以配置缓存过期和使用缓存提供物理缓存属性。

并发策略:
并发策略是一个中介的负责存储数据项在缓存并从缓存中检索它们。如果要启用二级缓存,将必须决定,为每个持久化类和集合,要使用的缓存并发策略。

Transactional: 使用这种策略的主要读取数据的地方,以防止过时的数据的并发事务,在更新的罕见情况下是至关重要的。

Read-write: 再次使用这种策略的主要读取数据的地方,以防止并发事务陈旧的数据是至关重要的,在更新的罕见情况。

Nonstrict-read-write: 这种策略不保证缓存与数据库之间的一致性。使用此策略,如果数据很少改变和陈旧数据的可能性很小关键是不关注。

Read-only: 并发策略适用于数据,永远不会改变。使用数据仅供参考。

如果我们要使用第二级缓存为我们的Employee类,让我们添加告诉Hibernate使用可读写的高速缓存策略Employee实例所需的映射元素。

<?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使用一个可读写的并发策略定义的缓存。

缓存提供者:
考虑到会用你的缓存候选类的并发策略后,下一步就是选择一个缓存提供程序。Hibernate迫使选择一个缓存提供整个应用程序。

Explication détaillée des annotations et de la mise en cache dans le framework Hibernate de Java

在指定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>

现在,需要指定缓存区域的属性。EHCache都有自己的配置文件ehcache.xml,在应用程序在CLASSPATH中。在ehcache.xml中Employee类高速缓存配置可能看起来像这样:

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

就这样,现在启用Employee类的二级缓存和Hibernate现在二级缓存,每当浏览到一个雇员或当通过标识符加载雇员。

应该分析你所有的类,并选择适当的缓存策略为每个类。有时,二级缓存可能降级的应用程序的性能。所以建议到基准应用程序第一次没有启用缓存,非常适合缓存和检查性能。如果缓存不提高系统性能再有就是在使任何类型的缓存是没有意义的。

查询级别缓存:
使用查询缓存,必须先使用 hibernate.cache.use_query_cache="true"属性配置文件中激活它。如果将此属性设置为true,让Hibernate的在内存中创建所需的高速缓存来保存查询和标识符集。

接下来,使用查询缓存,可以使用Query类的setCacheable(Boolean)方法。例如:

Session session = SessionFactory.openSession();

Query query = session.createQuery("FROM EMPLOYEE");

query.setCacheable(true);

List users = query.list();

SessionFactory.closeSession();

Hibernate也支持通过一个缓存区域的概念非常细粒度的缓存支持。缓存区是这是给定一个名称缓存的一部分。

Session session = SessionFactory.openSession();

Query query = session.createQuery("FROM EMPLOYEE");

query.setCacheable(true);

query.setCacheRegion("employee");

Liste des utilisateurs = query.list();

SessionFactory.closeSession();

Cette méthode d'utilisation du code indique Hibernate est utilisé pour stocker et rechercher les aspects de la requête des employés dans le cache.

Pour des articles plus détaillés sur les annotations et la mise en cache dans le framework Java Hibernate, veuillez faire attention au site Web PHP chinois !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn