>  기사  >  Java  >  Java Hibernate 프레임워크의 주석 및 캐싱에 대한 자세한 설명

Java Hibernate 프레임워크의 주석 및 캐싱에 대한 자세한 설명

高洛峰
高洛峰원래의
2017-01-23 11:53:301168검색

주석
Hibernate 주석은 XML 파일을 사용하지 않고 매핑을 정의하는 새로운 방법입니다. XML 매핑 메타데이터에 추가로 또는 대체하여 주석을 사용할 수 있습니다.

Hibernate 주석은 메타데이터 개체와 관계형 테이블 간의 매핑을 제공하는 강력한 방법입니다. 모든 메타데이터는 사용자가 개발 프로세스 중에 테이블 구조와 POJO를 모두 이해하는 데 도움이 되는 POJO Java 파일의 코드로 함께 묶입니다.

애플리케이션을 다른 EJB3 사양 ORM 애플리케이션으로 포팅하려는 경우 주석을 사용하여 매핑 정보를 표현해야 하지만, 여전히 더 큰 유연성을 원한다면 XML 기반 매핑을 사용해야 합니다.

환경 설정 Hibernate 주석
먼저 JDK5.0을 사용하고 있는지 확인해야 합니다. 그렇지 않은 경우 기본 주석 지원을 활용하려면 JDK를 JDK5.0으로 업그레이드해야 합니다.

두 번째로, SourceForge에서 얻을 수 있는 Hibernate 3.x 주석 배포 패키지를 설치해야 합니다: (Hibernate Annotation 다운로드) 그리고 hibernate-annotations.jar, lib/hibernate-comons-annotations.jar을 복사하세요. lib/ejb3 -persistence.jar Hibernate 주석의 클래스 인스턴스를 CLASSPATH

주석에 할당합니다.
Hibernate 주석을 사용하는 동안 언급했듯이 모든 메타데이터는 위의 코드와 함께 POJO Java 파일로 작동합니다. 이는 개발 과정에서 사용자가 테이블 구조와 POJO를 동시에 이해할 수 있도록 도와줍니다.

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

다음은 Employee 클래스의 개체를 정의된 개체와 매핑하기 위해 주석을 사용하는 매핑입니다. EMPLOYEE 테이블:

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는 @Id 주석이 필드에 있음을 감지하고 런타임 도메인을 통해 객체의 속성으로 직접 액세스해야 한다고 가정합니다. getId() 메서드에 @Id 주석을 추가하면 기본적으로 getter 및 setter 메서드를 통해 속성에 대한 액세스가 허용됩니다. 따라서 다른 모든 주석도 선택한 전략에 따라 필드 또는 getter 메서드에 배치됩니다. 다음 섹션에서는 위 클래스에서 사용된 Annotation에 대해 설명합니다.

@Entity 참고:
EJB3 사양은 javax.persistence 패키지에 포함되어 있으므로 첫 번째 단계로 이 패키지를 가져옵니다. 둘째, @Entity 주석을 사용하여 이 클래스를 엔터티 Bean Employee 클래스로 표시했으므로 보호된 범위에서 최종적으로 표시되는 매개변수 없는 생성자가 있어야 합니다.

@Table 주석:
@Table 주석을 사용하면 지정된 테이블을 사용하여 이 엔터티의 세부 정보를 데이터베이스에 저장할 수 있습니다.

@Table 주석은 테이블 이름, 디렉터리, 스키마를 재정의하고 테이블 내 열에 고유 제약 조건을 적용할 수 있는 네 가지 속성을 제공합니다. 이제 방금 부여한 EMPLOYEE 테이블의 이름을 사용하고 있습니다.

@Id 및 @GeneratedValue 주석:
각 엔터티 Bean에는 클래스의 @Id 주석에 주석이 달린 기본 키가 있습니다. 기본 키는 테이블 구조에 따라 단일 필드일 수도 있고 여러 필드의 조합일 수도 있습니다.

기본적으로 @Id 주석은 사용할 가장 적절한 기본 키 생성 전략을 자동으로 결정하지만 이는 의도하지 않은 전략 및 생성기라는 두 매개변수를 허용하는 @GeneratedValue 주석을 적용하여 달성할 수 있습니다. 여기에서는 기본 기본 키 생성 정책을 사용하면 됩니다. Hibernate가 사용할 생성기 유형을 결정하도록 하면 코드가 서로 다른 데이터베이스 간에 이식 가능해집니다.

@Column 주석:
@Column 주석은 필드나 속성이 매핑될 열의 세부정보를 지정하는 데 사용됩니다. 가장 일반적으로 사용되는 다음 속성은 열 주석과 함께 사용할 수 있습니다.

이름 속성을 사용하면 열 이름을 명시적으로 지정할 수 있습니다.

length 속성을 사용하면 열의 크기를 사용하여 값, 특히 문자열 값을 매핑할 수 있습니다.

nullable 특성을 사용하면 스키마 생성 시 열이 NOT NULL로 표시될 수 있습니다.

unique 속성을 사용하면 열에 고유한 값만 포함된 것으로 표시할 수 있습니다.

애플리케이션 클래스 생성:
마지막으로 애플리케이션을 실행하기 위한 애플리케이션 클래스의 main() 메서드를 생성합니다. 이 애플리케이션을 사용하여 일부 직원 기록을 저장한 다음 해당 기록에 CRUD 작업을 적용하겠습니다.

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

데이터베이스 구성:
이제 데이터베이스의 관련 매개변수를 정의하기 위해 hibernate.cfg.xml 구성 파일을 생성해 보겠습니다.

<?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>

컴파일 및 실행:
다음은 위 애플리케이션을 컴파일하고 실행하는 단계입니다. 컴파일 및 실행 전에 PATH 및 CLASSPATH가 적절하게 설정되었는지 확인하십시오.

경로에서 Employee.hbm.xml 매핑 파일을 제거하세요.

위 그림과 같이 Employee.java 소스 파일을 생성하고 컴파일합니다.

위 그림과 같이 ManageEmployee.java 소스 파일을 생성하고 컴파일합니다.

ManageEmployee 바이너리를 실행하여 프로그램을 실행합니다.

은 다음과 같은 결과를 얻고 레코드는 EMPLOYEE 테이블에 저장됩니다.

$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

EMPLOYEE 테이블을 확인하면 다음 레코드가 있어야 합니다.

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>

캐시
캐시는 애플리케이션 성능 최적화에 관한 것이며 다음 위치에 있습니다. 여러 데이터베이스 액세스를 방지하여 성능이 중요한 애플리케이션의 성능을 향상시킵니다.

캐싱은 아래 설명된 것처럼 다중 레벨 캐싱 방식을 사용하는 Hibernate에 매우 중요합니다.

Java Hibernate 프레임워크의 주석 및 캐싱에 대한 자세한 설명

第一级缓存:
第一级缓存是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迫使选择一个缓存提供整个应用程序。

Java Hibernate 프레임워크의 주석 및 캐싱에 대한 자세한 설명

在指定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");

사용자 나열 = query.list();

SessionFactory.closeSession();

이 코드 사용 방법은 Hibernate는 쿼리의 직원 측면을 캐시에 저장하고 조회하는 데 사용됩니다.

Java Hibernate 프레임워크의 주석 및 캐싱에 대한 자세한 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.