Запрос Java Hibernate
View more Tutorials:
Данная статья является ссылкой для некоторых вопросов связанных с Hibernate. Чтобы легче понять, вам стоит просмотреть статью:
Когда вы работаете с определенной базой данных, вам нужна библиотека, чтобы управлять этим видом базы данных.
- Oracle
- MySQL
- SQLServer
- HSQL
- ....
Смотрите так же:
Мы получаем результат:

Сперва вам нужно объявить библиотеки управляющие базой данных 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>
Для начала вам нужно объявить библиотеки упраляющие базой данных 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>
Для начала, вам нужно объявить библиотеку, которая управляет базой данных 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>
Hibernate использует Annotation чтобы описать информацию для Entity. Он может использовать annotation в API у hibernate расположенный в пакете org.hibernate.annotations. Или использовать Annotation расположенные в пакете javax.persistence у Java Persistence API. На самом деле все Annotation в Java Persistence API являются больше всего предпочитаемыми.
В этой части я перечислю все самые распространенные Annotation в Java Persistence API которые принимают участие в аннотации для Entity.
В этой части я перечислю все самые распространенные Annotation в Java Persistence API которые принимают участие в аннотации для 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";
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; } }
Например @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; } ...... }
@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
Иногда он также аннотирован с @Generator
// 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 и его значение может само увеличиваться.
Столбец с видом IDENTITY только поддерживаются некоторыми видами баз данных, а всеми, например MySQL, DB2, SQL Server, Sybase и Postgres. Oracle не поддерживают данный вид столбца.
@GeneratedValue(strategy=GenerationType.IDENTITY) @Id @Column(name = "EMP_ID") public Integer getEmpId() { return empId; }
SEQUENCE это объект в базе данных, хранящий возрастающее значение после каждого вызова, чтобы получить следующее значение, и поддерживается с помощью Oracle, DB2, и Postgres.
@GeneratedValue(strategy=GenerationType.SEQUENCE) @Id @Column(name = "EMP_ID") public Integer getEmpId() { return empId; }

@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)
UUID это класс Java позволяющий вам создать случайную строку с 36 символами. И с 36 символами, вероятность совпадения очень мала.
Вы так же можете аннотировать, чтобы Hibernate сгенерировал случайную строку данного вида, прикрепленную к значению столбца.
Вы так же можете аннотировать, чтобы 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; }
@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; }
@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; }
@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; }
@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().
На самом деле hibernate еще не скачивает данные из соответствующих записей таблицы BRANCH в этот объект. Он только выполняет запрос данных когда вы что-то делаете с объектом только что полученным Branch, например вызвать метод branch.getName().
EAGER:
EAGER говорит Hibernate сделать запрос всех связанных столбцов.
Например у вас есть объект Account, и вызываете метод getOpenBranch() возвращает Branch с готовыми значениями для полей (name, address, ...). На самом деле его данные получены в одном запросе с таблицей Account.
Вам стоит использовать LAZY вместо EAGER из-за производительности программы .
@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; } }
@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; } }
Рассмотрим ситуацию:
@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; }