Запрос Java Hibernate

View more categories:

1- Введение

Данная статья является ссылкой для некоторых вопросов связанных с Hibernate. Чтобы легче понять, вам стоит просмотреть статью:
  • TODO Link!

2- Скачать библиотеки управляющие некоторые виды баз данных

Когда вы работаете с определенной базой данных, вам нужна библиотека, чтобы управлять этим видом базы данных.
  • Oracle
  • MySQL
  • SQLServer
  • HSQL
  • ....
Смотрите так же:
Мы получаем результат:

3- Конфигурация Hibernate на разных видах баз данных.

3.1- Конфигурация Hibernate для Oracle.

Сперва вам нужно объявить библиотеки управляющие базой данных Oracle (Руководство выше).
Конфигурация  Hibernate:
hibernate.cfg.xml (Oracle)
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>  
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:db11g</property>    
<property name="connection.username">simplehr</property>
<property name="connection.password">1234</property>


<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">2</property>

<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>

<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>


<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>


 <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
 <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
 <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
 <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />

</session-factory>
</hibernate-configuration>

3.2- Конфигурация Hibernate для MySQL

Для начала вам нужно объявить библиотеки упраляющие базой данных MySQL (Руководство выше).
Конфигурация  Hibernate
hibernate.cfg.xml (MySQL)
<?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>
 <!-- Database connection settings -->
 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 <property name="connection.url">jdbc:mysql://tran-vmware:3306/simplehr</property>
 <property name="connection.username">root</property>
 <property name="connection.password">1234</property>

 <!-- JDBC connection pool (use the built-in) -->
 <property name="connection.pool_size">1</property>

 <!-- SQL dialect -->
 <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

 <!-- Enable Hibernate's automatic session context management -->
 <property name="current_session_context_class">thread</property>

 <!-- Disable the second-level cache  -->
 <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

 <!-- Echo all executed SQL to stdout -->
 <property name="show_sql">true</property>

  <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
  <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
  <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
  <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />

</session-factory>
</hibernate-configuration>

3.3- Конфигурация Hibernate для SQL Server

Для начала, вам нужно объявить библиотеку, которая управляет базой данных  SQLServer (Руководство выше).

Конфигурация  Hibernate (Используя библиотеку  JTDS)
hibernate.cfg.xml (SQL Server)
<?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>
  <!-- Database connection settings -->
  <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
  <property name="connection.url">jdbc:jtds:sqlserver://localhost:1433/simplehr;instance=SQLEXPRESS</property>
  <property name="connection.username">sa</property>
  <property name="connection.password">1234</property>

  <!-- JDBC connection pool (use the built-in) -->
  <property name="connection.pool_size">1</property>

  <!-- SQL dialect -->
  <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>

  <!-- Enable Hibernate's automatic session context management -->
  <property name="current_session_context_class">thread</property>

  <!-- Disable the second-level cache  -->
  <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

  <!-- Echo all executed SQL to stdout -->
  <property name="show_sql">true</property>

   <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />

</session-factory>
</hibernate-configuration>

4- Hibernate & Java Persistence Annotation

Hibernate использует  Annotation чтобы описать информацию для  Entity. Он может использовать annotation в API у hibernate расположенный в пакете  org.hibernate.annotations. Или использовать  Annotation расположенные в пакете  javax.persistence у Java Persistence API. На самом деле все Annotation в Java Persistence API являются больше всего предпочитаемыми.

В этой части я перечислю все самые распространенные Annotation в  Java Persistence API которые принимают участие в аннотации для  Entity.

4.1- @Entity

@Entity используемый для аннотации класса является  Entity.
// Phần tử (element) name của @Entity là không bắt buộc.
// Việc chỉ định rõ name của @Entity cho phép viết ngắn câu HSQL

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

// Phần tử (element) name của @Entity là không bắt buộc.
// Entity khớp với một bảng lấy theo tên theo thứ tự ưu tiên:
//  1 - name trong @Table
//  2 - name trong @Entity
//  3 - name của class.
// Việc chỉ định rõ name của @Entity cho phép viết ngắn câu HSQL

@Entity(name="AccTransaction")
@Table(name = "ACC_TRANSACTION")
public class AccTransaction implements Serializable {

}
 
Ясное определение элемента  name у @Entity помогает вам укоротить команду  HSQL. Смотрите иллюстрированный пример:
// @Entity chú thích trên class Account không chỉ định rõ phần tử name.
// Vì vậy câu HSQL bắt buộc phải viết:

String hsql1 = "Select o from "+ Account.class.getName() +" o ";


// @Entity chú thích trên class AccTransaction
// chỉ định rõ phần tử name = "AccTransaction"
// Vì vậy câu HSQL có thể viết ngắn gọn:

String hsql2 = "Select o from AccTransaction o";

4.2- @Table

Table в базе данных может иметь много уникальных ограничений. @Table так же позволяет вам аннотировать это.
// @Table cho phép chú thích tên bảng
// Các giàng buộc duy nhất trong bảng.
// Phần tử name không bắt buộc.
// Nếu bạn không chỉ rõ tên bảng trong phần tử name ...
// .. Hibernate sẽ dựa vào phần tử name của @Entity sau đó mới
// tới tên của class.

@Table( name = "invoice_header",
           uniqueConstraints = @UniqueConstraint(columnNames ={ "invoice_num" }   )
)
@Entity
public class InvoiceHeader  implements java.io.Serializable {

       private String invoiceNum;


      @Column(name = "invoice_num", nullable = false, length = 20)
      public String getInvoiceNum() {
          return this.invoiceNum;
      }

}

4.3- @Id

Например  @Id участвует в аннотации  ID (Identity) в Entity, соответствует с пониманием, что этот столбец и есть главный ключ таблицы ( Primary Key).
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {

    private Integer empId;

    // @Id chú thích đây là id của Entity.
    // Và EMP_ID chính là khóa chính (Primary Key) của bảng.

    @Id
    @GeneratedValue
    @Column(name = "EMP_ID")
    public Integer getEmpId() {
        return empId;
    }

     ......
}

4.4- @GeneratedValue

@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeneratedValue {

  // GenerationType: AUTO, TABLE, SEQUENCE, IDENTITY
  GenerationType strategy() default AUTO;

  String generator() default "";

}
@GeneratedValue аннотирован чтобы  Hibernate автоматически генерировал значение и прикреплял его в столбец в случае insert (вставления) нового  Entity в базу данных. Оно может быть прикреплено к столбцу ID или к другому определенному столбцу.

Иногда он также аннотирован с  @Generator

4.4.1- GenerationType.AUTO

// Chú thích @GeneratedValue tương đương với
// @GeneratedValue(strategy=GenerationType.AUTO)

@GeneratedValue
@Id
@Column(name = "EMP_ID")
public Integer getEmpId() {
    return empId;
}
Столбец аннотированный  @GeneratedValue(strategy= AUTO) будет иметь автоматически прикрепленное значение, которое может быть генерировано с помощью  SEQUENCE или само увеличиваться (Если этот столбец имеет вид  IDENTITY). Он зависит от вида  DB.
С  Oracle, Postgres, hibernate вызовет  Sequence с названием  Hibernate_Sequence чтобы создать возрастающее значение, для прикрепления значений к данному столбцу. С другмими  DB, как  MySQL, DB2, SQL Server, Sysbase столбец может иметь вид  IDENTITY и его значение может само увеличиваться.

4.4.2- GenerationType.IDENTITY

Столбец с видом  IDENTITY только поддерживаются некоторыми видами баз данных, а всеми, например  MySQL, DB2, SQL Server, Sybase и  Postgres. Oracle не поддерживают данный вид столбца.
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
@Column(name = "EMP_ID")
public Integer getEmpId() {
   return empId;
}

4.4.3- GenerationType.SEQUENCE

SEQUENCE это объект в базе данных, хранящий возрастающее значение после каждого вызова, чтобы получить следующее значение, и поддерживается с помощью  Oracle, DB2, и Postgres.
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Id
@Column(name = "EMP_ID")
public Integer getEmpId() {
   return empId;
}

4.4.4- GenerationType.TABLE

@Entity
public class Employee {
    ...
    @TableGenerator(
        name="empGen",
        table="ID_GEN_TABLE",
        pkColumnName="KEY_COLUMN",
        valueColumnName="VALUE_COLUMN",
        pkColumnValue="EMP_ID",
        allocationSize=1)
    @Id
    @GeneratedValue(strategy=TABLE, generator="empGen")
    public Long getEmpId()  {
       return empId;
    }
    ...
}


@Entity
public class Department {
    ...
    @TableGenerator(
        name="deptGen",
        table="ID_GEN_TABLE",
        pkColumnName="KEY_COLUMN",
        valueColumnName="VALUE_COLUMN",
        pkColumnValue="DEPT_ID",
        allocationSize=1)
    @Id
    @GeneratedValue(strategy=TABLE, generator="deptGen")
    public Long getDeptId()  {
       return deptId;
    }
    ...
}
 

Примечание: Вы можете кастомизировать название таблицы, название столбца (ID_GEN_TABLE, KEY_COLUMN, VALUE_COLUMN)

4.4.5- UUID

UUID это класс  Java позволяющий вам создать случайную строку с 36 символами. И с 36 символами, вероятность совпадения очень мала.

Вы так же можете аннотировать, чтобы  Hibernate сгенерировал случайную строку данного вида, прикрепленную к значению столбца.
 // Sử dụng strategy = "uuid2".

@GenericGenerator(name="my-uuid", strategy = "uuid2")
@GeneratedValue(generator="my-uuid")
@Id
@Column(name = "EMP_ID", length = 36)
public String getEmpId()  {
   return empId;
}

4.5- @Column

@Column аннотирует одному столбцу, включая информацию длины столбца, позволяя null или нет
// Đây là một cột kiểu chuỗi, vì thế length luôn có ý nghĩa và cần thiết
// nullable mặc định là true
// length mặc định là 255

@Column(name = "FIRST_NAME", length = 20, nullable = false)
public String getFirstName() {
    return firstName;
}


// @Column không chỉ rõ phần tử length, mặc định nó là 255.

@Column(name = "DESCRIPTION", nullable = true )
public String getDescription() {
    return firstName;
}

// Với các cột kiểu số hoặc Date bạn có thể bỏ qua length
// (Nó không có ý nghĩa trong trường hợp này).

@Column(name = "PENDING_BALANCE")
public Float getPendingBalance() {
    return pendingBalance;
}




 

4.6- @Lob

@Lob обычно аннотируется с  @Column чтобы сказать что этот столбец является видом  BLOB или  CLOB.
// Chú ý rằng trong một số Database có phân biệt TINY, MEDIUM, LARGE BLOB/CLOB.
// Còn một số database thì không.
// Phần tử length trong @Column trong trường hợp này sẽ quyết định nó map
// vào BLOB/CLOB nào.
// Trong trường hợp cho phép BLOB/CLOB tối đa hãy để length = Integer.MAX_VALUE


// Method này trả về byte[]
// @Lob trong trường hợp này chú thích cho cột BLOB

@Lob
@Column(name = "IMAGE_VALUE", nullable = true, length = Integer.MAX_VALUE)
public byte[] getImageValue() {
    this.imageValue;
}

// Method này trả về String
// @Lob trong trường hợp này sẽ chú thích cho CLOB.

@Lob
@Column(name = "ARTICLE_CONTENT", nullable = true, length = Integer.MAX_VALUE)
public String getArticleContent() {
    this.articleContent;
}

4.7- @Temporal

@Temporal используется для аннотации столбца даты и времени (date time).
// @Temporal sử dụng chú thích cho cột có kiểu dữ liệu ngày tháng.
// Có 3 giá trị cho TemporalType:
// 1 - TemporalType.DATE
// 2 - TemporalType.TIME
// 3 - TemporalType.TIMESTAMP

@Temporal(TemporalType.DATE)
@Column(name = "START_DATE", nullable = false)
public java.util.Date getStartDate() {
    return startDate;
}

// TemporalType.DATE chú thích cột sẽ lưu trữ ngày tháng năm (bỏ đi thời gian)
// TemporalType.TIME chú thích cột sẽ lưu trữ thời gian (Giờ phút giây)
// TemporalType.TIMESTAMP chú thích cột sẽ lưu trữ ngày tháng và cả thời gian

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "FUNDS_AVAIL_DATE", nullable = false)
public java.util.Date getFundsAvailDate() {
      return fundsAvailDate;
}

4.8- @ManyToOne

@ManyToOne описывает отношение  N-1 (Много - один), обычно используется вместе с  @JoinColumn.
@Entity
@Table(name = "ACCOUNT")
public class Account implements Serializable {

 
    private Branch openBranch;
 
   // Phần tử foreignKey giúp chỉ rõ tên Foreign Key trong DB.
   // Điều này sẽ giúp Hibernate tạo ra DB từ các Entity java một cách chính xác hơn.

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "OPEN_BRANCH_ID", nullable = false,
                 foreignKey = @ForeignKey(name = "ACCOUNT_BRANCH_FK"))
    public Branch getOpenBranch() {
        return openBranch;
    }

}
Hibernate имеет инструменты, которые позволяют вам генерировать классы  Entity из таблиц в базе данных. И Hibernate так же позволяет вам генерировать таблицу из  Entity, включая ограничения между таблицами (Foreign Key). Аннотация  @ForeignKey позволяет определить имя  Foreign Key который будет создан.
@ForeignKey введен в  JPA с версии  2.1
// Phần tử fetch có 2 giá trị
// 1 - FetchType.LAZY
// 2 - FetchType.EAGER

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "OPEN_BRANCH_ID", nullable = false,
             foreignKey = @ForeignKey(name = "ACCOUNT_BRANCH_FK"))
public Branch getOpenBranch() {
    return openBranch;
}

LAZY:

LAZY говорит  Hibernate, что вы можете скачать данные "ленивым" способом.
Например у вас есть объект  Account, и вызывая метод  getOpenBranch() он возвращает объект  Branch, в объекте  Branch только к полю (field) branchId прикреплено значение, а к другим полям нет.

На самом деле  hibernate еще не скачивает данные из соответствующих записей таблицы  BRANCH в этот объект. Он только выполняет запрос данных когда вы что-то делаете с объектом только что полученным  Branch, например вызвать метод  branch.getName().

EAGER:

EAGER говорит  Hibernate сделать запрос всех связанных столбцов.
Например у вас есть объект  Account, и вызываете метод  getOpenBranch() возвращает  Branch с готовыми значениями для полей ( name, address, ...). На самом деле его данные получены в одном запросе с таблицей Account.
Вам стоит использовать  LAZY вместо  EAGER из-за производительности программы .

4.9- @OneToMany

@OneToMany это способ аннотации чтобы получить список дочерних записей настоящей записи (Это отношение один к многим). Является обратным  @ManyToOne, поэтому основывается на аннотацию  @ManyToOne чтобы определить  @OneToMany.
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {

    ....

    private Department department;
 
    // Quan hệ N-1 (Nhiều - Một) định nghĩa department.   

    @JoinColumn(name = "DEPT_ID", nullable = true,
              foreignKey = @ForeignKey(name = "EMPLOYEE_DEPARTMENT_FK"))    
    @ManyToOne(fetch = FetchType.LAZY)    
    public Department getDepartment() {
        return department;
    }
 

}



@Entity
@Table(name = "DEPARTMENT")
public class Department implements Serializable {

        .....

    private Set<Employee> employees = new HashSet<Employee>(0);

    // Quan hệ 1-N (Một - Nhiều) sử dụng mappedBy = "department"
    // đã định nghĩa ở quan hệ N-1 (phía trên).

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
    public Set<Employee> getEmployees() {
        return employees;
    }
}

4.10- @OrderBy

@OrderBy используется для организации коллекции, поэтому он используется вместе с @OneToMany:

@Entity
@Table(name = "DEPARTMENT")
public class Department implements Serializable {

        .....

    private Set<Employee> employees = new HashSet<Employee>(0);

    // Mặc định @OrderBy("empNo") tương đương với @OrderBy("empNo asc").
    // Nó tạo ra câu SQL: Select ... from Employee ... order by EMP_NO desc

    @OrderBy("empNo desc")
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
    public Set<Employee> getEmployees() {
        return employees;
    }
}

4.11- @Transient

Рассмотрим ситуацию:
@Entity
@Table(name="Employee")
public class Employee implements Serializable {
 
      .....

      @Column(name="FIRST_NAME", nullable =false , length = 20 )
      public String getFirstName()  {
           return this.firstName;
      }

      @Column(name="LAST_NAME", nullable =false , length = 20)
      public String getLastName()  {
           return this.lastName;
      }

     public String getFullName()  {
          return this.firstName+ " "+ this.lastName;
     }
}
Вы хотите написать метод  getFullName(), этот метод просто является расчетом, не имеет отношения ни к каким столбцам ниже DB. Поэтому вам необходимо использовать  @Transient чтобы объявить ваше намерение с  Hibernate.
@Transient
public String getFullName()  {
     return this.firstName+ " " + this.lastName;
}

@Transient
public boolean isManagerEmployee()  {
      return this.manager != null;
}

4.12- @Inheritance

View more categories: