- Préparation la Database
- Créer Maven Project & Déclarer la bibliothèque
- Des classes Entity
- Configurer Hibernate
- SessionFactory
- Hibernate Query Language (HQL)
- Requêter des données avec Hibernate
- Transient, Persistent et Detached
- Cycle de la vie de Hibernate (Hibernate Lifecycle)
- L'action Insert, Update, Delete với Hibernate
- Générer des tableaux à partir des classes Entity
Le Tutoriel de Java Hibernate
1. Préparation la Database
Hibernate est une bibliothèque constituée pour travailler avec tous les types de DB, elle ne dépend pas de type de DB que vous choisissez. Si Java est "Écrire une fois, exécuter partout"Hibernate sera "Écrire une fois, exécuter sur tous les types de DB"
Dans cet article, j'utilise le simplehr, ce qui est une base de données simple utilisée dans la plupart des tutoriels sur o7planning. Vous pouvez la créer avec une des bases de données telles que Oracle, MySQL ou SQL Server. Suivez les instructions ci-dessous :
2. Créer Maven Project & Déclarer la bibliothèque
Ici, je crée un projet Maven et déclare les bibliothèques Hibernate dans pom.xml.
- File/New/Other...
Project is created.
Dans pom.xml je déclare la bibliothèque Hibernate 5 et les bibliothèques JDBC pour différentes bases de données telles que Oracle, MySQL et SQL Server.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.o7planning</groupId>
<artifactId>HibernateTutorial</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>HibernateTutorial</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<!-- Repository for ORACLE JDBC Driver -->
<repository>
<id>codelds</id>
<url>https://code.lds.org/nexus/content/groups/main-repo</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Hibernate Core -->
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.2.Final</version>
</dependency>
<!-- MySQL JDBC driver -->
<!-- http://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<!-- Oracle JDBC driver -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<!-- SQLServer JDBC driver (JTDS) -->
<!-- http://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
</project>
3. Des classes Entity
Nous créonss la classe Entity. Chaque Entity représente un tableau dans la DB. Mais on en parlerons plus tard.
- Department - Département
- Employee - Employé
- SalaryGrade - Grille de salaire
- Timekeeper - Chronomètre, l'heure d'entrant des employés.
Department.java
package org.o7planning.tutorial.hibernate.entities;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@Entity
@Table(name = "DEPARTMENT",
uniqueConstraints = { @UniqueConstraint(columnNames = { "DEPT_NO" }) })
public class Department {
private Integer deptId;
private String deptNo;
private String deptName;
private String location;
private Set<Employee> employees = new HashSet<Employee>(0);
public Department() {
}
public Department(Integer deptId, String deptName, String location) {
this.deptId = deptId;
this.deptNo = "D" + this.deptId;
this.deptName = deptName;
this.location = location;
}
@Id
@Column(name = "DEPT_ID")
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
@Column(name = "DEPT_NO", length = 20, nullable = false)
public String getDeptNo() {
return deptNo;
}
public void setDeptNo(String deptNo) {
this.deptNo = deptNo;
}
@Column(name = "DEPT_NAME", nullable = false)
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
@Column(name = "LOCATION")
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
}
Employee.java
package org.o7planning.tutorial.hibernate.entities;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
@Entity
@Table(name = "EMPLOYEE",
uniqueConstraints = { @UniqueConstraint(columnNames = { "EMP_NO" }) })
public class Employee {
private Long empId;
private String empNo;
private String empName;
private String job;
private Employee manager;
private Date hideDate;
private Float salary;
private byte[] image;
private Department department;
private Set<Employee> employees = new HashSet<Employee>(0);
public Employee() {
}
public Employee(Long empId, String empName, String job, Employee manager,
Date hideDate, Float salary, Float comm, Department department) {
this.empId = empId;
this.empNo = "E" + this.empId;
this.empName = empName;
this.job = job;
this.manager = manager;
this.hideDate = hideDate;
this.salary = salary;
this.department = department;
}
@Id
@Column(name = "EMP_ID")
public Long getEmpId() {
return empId;
}
public void setEmpId(Long empId) {
this.empId = empId;
}
@Column(name = "EMP_NO", length = 20, nullable = false)
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
@Column(name = "EMP_NAME", length = 50, nullable = false)
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
@Column(name = "JOB", length = 30, nullable = false)
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MNG_ID")
public Employee getManager() {
return manager;
}
public void setManager(Employee manager) {
this.manager = manager;
}
@Column(name = "HIRE_DATE", nullable = false)
@Temporal(TemporalType.DATE)
public Date getHideDate() {
return hideDate;
}
public void setHideDate(Date hideDate) {
this.hideDate = hideDate;
}
@Column(name = "SALARY", nullable = false)
public Float getSalary() {
return salary;
}
public void setSalary(Float salary) {
this.salary = salary;
}
@Column(name = "IMAGE", length = 1111111, nullable = true)
@Lob
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "DEPT_ID", nullable = false)
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "empId")
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
}
SalaryGrade.java
package org.o7planning.tutorial.hibernate.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "SALARY_GRADE")
public class SalaryGrade {
private Integer grade;
private Float lowSalary;
private Float highSalary;
public SalaryGrade() {
}
public SalaryGrade(Integer grade, Float lowSalary, Float highSalary) {
this.grade = grade;
this.lowSalary = lowSalary;
this.highSalary = highSalary;
}
@Id
@Column(name = "GRADE")
public Integer getGrade() {
return grade;
}
public void setGrade(Integer grade) {
this.grade = grade;
}
@Column(name = "LOW_SALARY", nullable = false)
public Float getLowSalary() {
return lowSalary;
}
public void setLowSalary(Float lowSalary) {
this.lowSalary = lowSalary;
}
@Column(name = "HIGH_SALARY", nullable = false)
public Float getHighSalary() {
return highSalary;
}
public void setHighSalary(Float highSalary) {
this.highSalary = highSalary;
}
}
Timekeeper.java
package org.o7planning.tutorial.hibernate.entities;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "TIMEKEEPER")
public class Timekeeper {
public static final char IN = 'I';
public static final char OUT = 'O';
private String timekeeperId;
private Date dateTime;
private Employee employee;
// 'I' or 'O'
private char inOut;
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(name = "Timekeeper_Id", length = 36)
public String getTimekeeperId() {
return timekeeperId;
}
public void setTimekeeperId(String timekeeperId) {
this.timekeeperId = timekeeperId;
}
@Column(name = "Date_Time", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
public Date getDateTime() {
return dateTime;
}
public void setDateTime(Date dateTime) {
this.dateTime = dateTime;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EMP_ID", nullable = false)
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
@Column(name = "In_Out", nullable = false, length = 1)
public char getInOut() {
return inOut;
}
public void setInOut(char inOut) {
this.inOut = inOut;
}
}
4. Configurer Hibernate
Le but est que Hibernate puisse lire Database et déclarer la liste des Entity que vous avez créées aux étapes précédentes.
Créez le fichier de configuration hibernate.cfg.xml situé dans src/main/java
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>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:db11g</property>
<property name="hibernate.connection.username">simplehr</property>
<property name="hibernate.connection.password">12345</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.connection.release_mode">auto</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.connection.autoReconnect">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.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?serverTimezone=UTC</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>
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>
Chaque Database différent a un Dialect (dialecte) différent.
Par exemple :
Dialect pour Oracle :
- org.hibernate.dialect.Oracle10gDialect (Oracle 10g &11g)
- org.hibernate.dialect.Oracle12cDialect
Dialect pour SQL Server :
- org.hibernate.dialect.SQLServerDialect
- org.hibernate.dialect.SQLServer2012Dialect
- org.hibernate.dialect.SQLServer2008Dialect
Dialect pour MySQL :
- org.hibernate.dialect.MySQLDialect
- org.hibernate.dialect.MySQL5Dialect
Remarque : org.hibernate.dialect.Oracle10gDialect est utilisé pour Oracle 10g, 11g, 12c.
Qu'est-ce que Dialect?
Dialect est une classe qui montre au Hibernate la manière de convertissement les types de données de Database au type de données Java, et vice versa. Elle sert également à définir le moyen de convertir des fonctions HSQL (Hibernate SQL) aux fonctions Database correspondantes.
Java SQL Type | Oracle | My SQL | SQL Server |
Types.BIT | number(1,0) | bit | bit |
Types.BIGINT | number(19,0) | bigint | bigint |
Types.DATE | date | date | date |
....... | |||
Types.CLOB | clob | longtext | varchar(MAX) |
Types.BLOB | blob | longblob | varbinary(MAX) |
5. SessionFactory
HibernateUtils est une classe utilitaire, elle a une méthode qui renvoie l'objet SessionFactory. Cette classe sera utilisée fréquemment dans des exemples.
HibernateUtils.java
package org.o7planning.tutorial.hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
public class HibernateUtils {
private static final SessionFactory sessionFactory = buildSessionFactory();
// Hibernate 5:
private static SessionFactory buildSessionFactory() {
try {
// Create the ServiceRegistry from hibernate.cfg.xml
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()//
.configure("hibernate.cfg.xml").build();
// Create a metadata sources using the specified service registry.
Metadata metadata = new MetadataSources(serviceRegistry).getMetadataBuilder().build();
return metadata.getSessionFactoryBuilder().build();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
// Close caches and connection pools
getSessionFactory().close();
}
}
6. Hibernate Query Language (HQL)
Hibernate utilise Hibernate Query Language (HQL) pour requêter des données. HQL est un peu différent du SQL que vous avez connu auparavant.
SQL:
- Query (Requêter) des données sur les tableaux.
HQL:
- Query (Requêter) des données sur les classes Entity.
-- SQL
-- This is a SQL query in table DEPARTMENT.
Select d.DEPT_NO, d.DEPT_NAME from DEPARTMENT d;
-- HQL
-- This is a HQL query in Entity Department.
Select d.deptNo, d.deptName from Department d;
-- Query Object
Select d from Department d;
The rules of operation of Hibernate:
Votre application écrit HQL. Lors de l'exécution, Hibernate est conscient de quel type Database avec lequel il travaille et il convertit automatiquement de HQL en SQL correspondant du type de DB. En fait, nous savons qu'il y a quelques différences de syntaxe SQL parmi des types Database différents.
Vous pouvez faire référence à la syntaxe de HQL dans le lien ci-dessous:
7. Requêter des données avec Hibernate
Il existe de nombreuses façons d'interroger des données dans Hibernate. Dans cette partie, je présenterai quelques méthodes classiques pour requêter des données.
Query Object utilise HQL
Le premier exemple, l'utilisation de HQL pour requêter des objets Entity :
QueryObjectDemo.java
package org.o7planning.tutorial.hibernate.query;
import java.util.List;
import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class QueryObjectDemo {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
try {
// All the action with DB via Hibernate
// must be located in one transaction.
// Start Transaction.
session.getTransaction().begin();
// Create an HQL statement, query the object.
// Equivalent to the SQL statement:
// Select e.* from EMPLOYEE e order by e.EMP_NAME, e.EMP_NO
String sql = "Select e from " + Employee.class.getName() + " e "
+ " order by e.empName, e.empNo ";
// Create Query object.
Query<Employee> query = session.createQuery(sql);
// Execute query.
List<Employee> employees = query.getResultList();
for (Employee emp : employees) {
System.out.println("Emp: " + emp.getEmpNo() + " : "
+ emp.getEmpName());
}
// Commit data.
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
// Rollback in case of an error occurred.
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Demo2:
QueryObjectDemo2.java
package org.o7planning.tutorial.hibernate.query;
import java.util.List;
import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class QueryObjectDemo2 {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
try {
// All the action with DB via Hibernate
// must be located in one transaction
// Start Transaction.
session.getTransaction().begin();
// Create an HQL statement, query the object.
// HQL with parameters.
// Equivalent to the SQL statement:
// Select e.* from EMPLOYEE e cross join DEPARTMENT d
// where e.DEPT_ID = d.DEPT_ID and d.DEPT_NO = :deptNo;
String sql = "Select e from " + Employee.class.getName() + " e "
+ " where e.department.deptNo=:deptNo ";
// Create query object.
Query<Employee> query = session.createQuery(sql);
query.setParameter("deptNo", "D10");
// Execute query.
List<Employee> employees = query.getResultList();
for (Employee emp : employees) {
System.out.println("Emp: " + emp.getEmpNo() + " : "
+ emp.getEmpName());
}
// Commit data
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
// Rollback in case of an error occurred.
session.getTransaction().rollback();
}
}
}
Query prend des données de quelques colonnes en utilisant HQL
QuerySomeColumnDemo.java
package org.o7planning.tutorial.hibernate.query;
import java.util.List;
import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class QuerySomeColumnDemo {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
try {
session.getTransaction().begin();
// Query some columns.
String sql = "Select e.empId, e.empNo, e.empName from "
+ Employee.class.getName() + " e ";
Query<Object[]> query = session.createQuery(sql);
// Execute Query.
// Get the array of Object
List<Object[]> datas = query.getResultList();
for (Object[] emp : datas) {
System.out.println("Emp Id: " + emp[0]);
System.out.println(" Emp No: " + emp[1]);
System.out.println(" Emp Name: " + emp[2]);
}
// Commit data.
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
// Rollback in case of an error occurred.
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Query prend des données de quelques colonnes en utilisant HQL & JavaBean
Dans ce cas, si vous devez extraire les données de certaines colonnes de certains tableaux, le meilleur moyen est à utiliser des Java beans. La classe Java beans aura un constructor vous permettant de définir des valeurs dans ses différents champs (fields). Ce Constructor participe à la requête HQL.
ShortEmpInfo.java
package org.o7planning.tutorial.hibernate.beans;
public class ShortEmpInfo {
private Long empId;
private String empNo;
private String empName;
//
// Constructor have 3 parameters, will be used in the Hibernate Query.
//
public ShortEmpInfo(Long empId, String empNo, String empName) {
this.empId = empId;
this.empNo = empNo;
this.empName = empName;
}
public Long getEmpId() {
return empId;
}
public void setEmpId(Long empId) {
this.empId = empId;
}
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
}
ShortEmpInfoQueryDemo.java
package org.o7planning.tutorial.hibernate.query;
import java.util.List;
import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.beans.ShortEmpInfo;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class ShortEmpInfoQueryDemo {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
try {
session.getTransaction().begin();
// Using constructor of ShortEmpInfo
String sql = "Select new " + ShortEmpInfo.class.getName()
+ "(e.empId, e.empNo, e.empName)" + " from "
+ Employee.class.getName() + " e ";
Query<ShortEmpInfo> query = session.createQuery(sql);
// Execute query.
// Get a List of ShortEmpInfo
List<ShortEmpInfo> employees = query.getResultList();
for (ShortEmpInfo emp : employees) {
System.out.println("Emp: " + emp.getEmpNo() + " : "
+ emp.getEmpName());
}
// Commit data.
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
// Rollback in case of an error occurred.
session.getTransaction().rollback();
}
}
}
Query récupère un résultat unique
UniqueResultDemo.java
package org.o7planning.tutorial.hibernate.query;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Department;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class UniqueResultDemo {
public static Department getDepartment(Session session, String deptNo) {
String sql = "Select d from " + Department.class.getName() + " d "//
+ " where d.deptNo= :deptNo ";
Query<Department> query = session.createQuery(sql);
query.setParameter("deptNo", deptNo);
return (Department) query.getSingleResult();
}
public static Employee getEmployee(Session session, Long empId) {
String sql = "Select e from " + Employee.class.getName() + " e "//
+ " where e.empId= :empId ";
Query<Employee> query = session.createQuery(sql);
query.setParameter("empId", empId);
return (Employee) query.getSingleResult();
}
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
try {
session.getTransaction().begin();
Department dept = getDepartment(session, "D10");
Set<Employee> emps = dept.getEmployees();
System.out.println("Dept Name: " + dept.getDeptName());
for (Employee emp : emps) {
System.out.println(" Emp name: " + emp.getEmpName());
}
Employee emp = getEmployee(session, 7839L);
System.out.println("Emp Name: " + emp.getEmpName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
8. Transient, Persistent et Detached
DataUtils.java
package org.o7planning.tutorial.hibernate;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.o7planning.tutorial.hibernate.entities.Department;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class DataUtils {
public static Department findDepartment(Session session, String deptNo) {
String sql = "Select d from " + Department.class.getName() + " d "//
+ " Where d.deptNo = :deptNo";
Query<Department> query = session.createQuery(sql);
query.setParameter("deptNo", deptNo);
return query.getSingleResult();
}
public static Long getMaxEmpId(Session session) {
String sql = "Select max(e.empId) from " + Employee.class.getName() + " e ";
Query<Number> query = session.createQuery(sql);
Number value = query.getSingleResult();
if (value == null) {
return 0L;
}
return value.longValue();
}
public static Employee findEmployee(Session session, String empNo) {
String sql = "Select e from " + Employee.class.getName() + " e "//
+ " Where e.empNo = :empNo";
Query<Employee> query = session.createQuery(sql);
query.setParameter("empNo", empNo);
return query.getSingleResult();
}
}
Ceci est un exemple simple utilisant Session.persist(Object) pour insérer un objet Transient à laDB. Le concept de l'objet Transitent, Persistent, Detached sera expliqué dans cet exemple.
PersistDemo.java
package org.o7planning.tutorial.hibernate.demo;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Department;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class PersistDemo {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
Department department = null;
Employee emp = null;
try {
session.getTransaction().begin();
Long maxEmpId = DataUtils.getMaxEmpId(session);
Long empId = maxEmpId + 1;
// Get Persistent object.
department = DataUtils.findDepartment(session, "D10");
// Create transient object
emp = new Employee();
emp.setEmpId(empId);
emp.setEmpNo("E" + empId);
emp.setEmpName("Name " + empId);
emp.setJob("Coder");
emp.setSalary(1000f);
emp.setManager(null);
emp.setHideDate(new Date());
emp.setDepartment(department);
// Using persist(..)
// Now 'emp' is managed by Hibernate.
// it has Persistent status.
// No action at this time with DB.
session.persist(emp);
// At this step the data is pushed to the DB.
// Execute Insert statement.
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
// After the session is closed (commit, rollback, close)
// Objects 'emp', 'dept' became the Detached objects.
// It is no longer in the control of the session.
System.out.println("Emp No: " + emp.getEmpNo());
}
}
Les résultats d'exécution de l'exemple :
9. Cycle de la vie de Hibernate (Hibernate Lifecycle)
La classe Session de Hibernate possède quelques méthodes importantes qui sont divisées en groupes comme l'illustration ci-dessous :
Un objet dans Hibernate exist sous un de quatres états :
- Transient (Temporaire)
- Persistent (Persistant)
- Removed (Effacé - sous DB)
- Detached (Séparé - en comparaison avec la session présente)
Nous allons expliquer ces états avec l'illustration ci-dessous :
Transient:
Si vous créez un nouvel objet java à partir un Entity, l'état de cet objet là sera Transient. Hibernate ne sait pas son existance. Il n'est pas géré par Hibernate.
Persistent
Dans le cas où vous récupérez des objets Entity via des méthodes get, load, find, getSingleResult,.. vous obtiendrez un objet qui correspond à un enregistrement sous la forme d'une base de données. L'état de cet objet est Persistent. Il est géré par Hibernate.
Transient -> Persistent
La Session appelle une des méthodes save, saveOrUpdate, persist, merge cela va pousser l'objet Transientà la gestion de Hibernate et cet objet change à l'état Persistent. Il est équivalant à l'action insert ou update dans la Database.
Persistent -> Detached
L'objet Session appelle la méthode evict(..) ou la méthode clear() pour renvoyer des objets Persistent en dehors de la gestion de Hibernate, en ce moment, ces objets obtiendront un nouvel état Detached (Détaché). S'ils ne sont pas rattachés (Re-Attached), ils seront ôtés par Java (Java Garbage Collector) selon le mécanisme normal.
Detached -> Persistent
L'utilisaton d'une des méthodes: update(..), saveOrUpdate(..), merge(..) va récupérer un objet en état Detached à la gestion de Hibernate. Cela équivaut à l'action update ou insert dans la Database. L'objet sera changer de l'état Persistent.
Persistent -> Removed
L'objet Session appelle des méthodes remove(..) ou delete(..) afin de supprimer un objet (Enregistrement). L'objet Persistent changera de l'état Removed (Supprimé).
10. L'action Insert, Update, Delete với Hibernate
Persistent
PersistentDemo.java
package org.o7planning.tutorial.hibernate.demo;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Department;
public class PersistentDemo {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
Department department = null;
try {
session.getTransaction().begin();
System.out.println("- Finding Department deptNo = D10...");
// Persistent object.
department = DataUtils.findDepartment(session, "D10");
System.out.println("- First change Location");
// Changing something on Persistent object.
department.setLocation("Chicago " + System.currentTimeMillis());
System.out.println("- Location = " + department.getLocation());
System.out.println("- Calling flush...");
// Use session.flush () to actively push the changes to the DB.
// It works for all changed Persistent objects.
session.flush();
System.out.println("- Flush OK");
System.out.println("- Second change Location");
// Change something on Persistent object
department.setLocation("Chicago " + System.currentTimeMillis());
// Print out location
System.out.println("- Location = " + department.getLocation());
System.out.println("- Calling commit...");
// Commit
session.getTransaction().commit();
System.out.println("- Commit OK");
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
// Create the session after it had been closed earlier
// (Cause by commit or update)
session = factory.getCurrentSession();
try {
session.getTransaction().begin();
System.out.println("- Finding Department deptNo = D10...");
// Query lại Department D10.
department = DataUtils.findDepartment(session, "D10");
// Print out location
System.out.println("- D10 Location = " + department.getLocation());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Transient --> Persistent : Vue d'ensemble
Transient --> Persistent : L'utilisation persist(Object)
PersistTransientDemo.java
package org.o7planning.tutorial.hibernate.demo;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
import org.o7planning.tutorial.hibernate.entities.Timekeeper;
public class PersistTransientDemo {
private static DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
private static Timekeeper persist_Transient(Session session, Employee emp) {
// Note:
// Configuring of timekeeperId
// @GeneratedValue(generator = "uuid")
// @GenericGenerator(name = "uuid", strategy = "uuid2")
Timekeeper tk1 = new Timekeeper();
tk1.setEmployee(emp);
tk1.setInOut(Timekeeper.IN);
tk1.setDateTime(new Date());
// Now, 'tk1' is transient object
System.out.println("- tk1 Persistent? " + session.contains(tk1));
System.out.println("====== CALL persist(tk).... ===========");
// Hibernate assign value to Id of 'tk1'
// No action to DB.
session.persist(tk1);
System.out
.println("- tk1.getTimekeeperId() = " + tk1.getTimekeeperId());
// Now 'tk1' is Persistent object.
// But no action with DB.
// ==> true
System.out.println("- tk1 Persistent? " + session.contains(tk1));
System.out.println("- Call flush..");
// Flush data to DB.
// Hibernate execute insert statement.
session.flush();
String timekeeperId = tk1.getTimekeeperId();
System.out.println("- timekeeperId = " + timekeeperId);
System.out.println("- inOut = " + tk1.getInOut());
System.out.println("- dateTime = " + df.format(tk1.getDateTime()));
System.out.println();
return tk1;
}
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
Employee emp = null;
try {
session.getTransaction().begin();
emp = DataUtils.findEmployee(session, "E7499");
persist_Transient(session, emp);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Transient --> Persistent : L'utilisation save(Object) *
SaveTransientDemo.java
package org.o7planning.tutorial.hibernate.demo;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
import org.o7planning.tutorial.hibernate.entities.Timekeeper;
public class SaveTransientDemo {
private static DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
private static Timekeeper persist_Transient(Session session, Employee emp) {
// See configuration of timekeeperId:
// @GeneratedValue(generator = "uuid")
// @GenericGenerator(name = "uuid", strategy = "uuid2")
// Create an Object, Transitent state.
Timekeeper tk2 = new Timekeeper();
tk2.setEmployee(emp);
tk2.setInOut(Timekeeper.IN);
tk2.setDateTime(new Date());
// Now 'tk3' are state Transient.
System.out.println("- tk2 Persistent? " + session.contains(tk2));
System.out.println("====== CALL save(tk).... ===========");
// save() very similar to persist()
// save() return ID, persist() return void.
// Hibernate assign ID value to 'tk2', no action with DB
// And return ID of 'tk2'.
Serializable id = session.save(tk2);
System.out.println("- id = " + id);
//
System.out
.println("- tk2.getTimekeeperId() = " + tk2.getTimekeeperId());
// Now, 'tk2' has Persistent state
// It has been managed in Session.
// ==> true
System.out.println("- tk2 Persistent? " + session.contains(tk2));
System.out.println("- Call flush..");
// To push data into the DB, call flush().
// If not call flush() data will be pushed to the DB when calling commit().
// Will execute insert statement.
session.flush();
String timekeeperId = tk2.getTimekeeperId();
System.out.println("- timekeeperId = " + timekeeperId);
System.out.println("- inOut = " + tk2.getInOut());
System.out.println("- dateTime = " + df.format(tk2.getDateTime()));
System.out.println();
return tk2;
}
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
Employee emp = null;
try {
session.getTransaction().begin();
emp = DataUtils.findEmployee(session, "E7499");
persist_Transient(session, emp);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Transient --> Persistent : L'utilisation saveOrUpdate(Object)
SaveOrUpdateTransientDemo.java
package org.o7planning.tutorial.hibernate.demo;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
import org.o7planning.tutorial.hibernate.entities.Timekeeper;
public class SaveOrUpdateTransientDemo {
private static DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
private static Timekeeper saveOrUpdate_Transient(Session session,
Employee emp) {
// See configuration of timekeeperId:
// @GeneratedValue(generator = "uuid")
// @GenericGenerator(name = "uuid", strategy = "uuid2")
// Create an Object, Transitent state.
Timekeeper tk3 = new Timekeeper();
tk3.setEmployee(emp);
tk3.setInOut(Timekeeper.IN);
tk3.setDateTime(new Date());
// Now 'tk3' are state Transient.
System.out.println("- tk3 Persistent? " + session.contains(tk3));
System.out.println("====== CALL saveOrUpdate(tk).... ===========");
// Here Hibernate checks, 'tk3' have ID or not (timekeeperId)
// If no, it will be assigned automatically
session.saveOrUpdate(tk3);
System.out
.println("- tk3.getTimekeeperId() = " + tk3.getTimekeeperId());
// Now 'tk3' has Persistent state
// It has been managed in Session.
// But no action insert, or update to DB.
// ==> true
System.out.println("- tk3 Persistent? " + session.contains(tk3));
System.out.println("- Call flush..");
// To push data into the DB, call flush().
// If not call flush() data will be pushed to the DB when calling commit().
// Now possible to Insert or Update DB. (!!!)
// Depending on the ID of 'tk3' exists in the DB or not
session.flush();
String timekeeperId = tk3.getTimekeeperId();
System.out.println("- timekeeperId = " + timekeeperId);
System.out.println("- inOut = " + tk3.getInOut());
System.out.println("- dateTime = " + df.format(tk3.getDateTime()));
System.out.println();
return tk3;
}
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
Employee emp = null;
try {
session.getTransaction().begin();
emp = DataUtils.findEmployee(session, "E7499");
saveOrUpdate_Transient(session, emp);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Transient --> Persistent : L'utilisation merge(Object)
MergeTransientDemo.java
package org.o7planning.tutorial.hibernate.demo;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
import org.o7planning.tutorial.hibernate.entities.Timekeeper;
public class MergeTransientDemo {
private static DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
private static Timekeeper saveOrUpdate_Transient(Session session,
Employee emp) {
// Note:
// Configuring of timekeeperId
// @GeneratedValue(generator = "uuid")
// @GenericGenerator(name = "uuid", strategy = "uuid2")
Timekeeper tk4 = new Timekeeper();
tk4.setEmployee(emp);
tk4.setInOut(Timekeeper.IN);
tk4.setDateTime(new Date());
// Now 'tk4' Transient status.
System.out.println("- tk4 Persistent? " + session.contains(tk4));
System.out.println("====== CALL merge(tk).... ===========");
// Hibernate2 has method saveOrUpdateCopy
// Hibernate3 change saveOrUpdateCopy to merge
// So there will be similarities between the two methods merge and copyOrUpdate
// Here Hibernate check tk4 has ID or not
// If not, Hibernate assign value to ID of tk4
// Return copy of tk4.
Timekeeper tk4Copy = (Timekeeper) session.merge(tk4);
System.out
.println("- tk4.getTimekeeperId() = " + tk4.getTimekeeperId());
// Now 'tk4' still Transient state.
// and 'tk4Copy' has Persistent status
// No action with DB (insert or update).
System.out.println("- tk4 Persistent? " + session.contains(tk4));
// 'tk4Copy' has Persistent status
// ==> true
System.out
.println("- tk4Copy Persistent? " + session.contains(tk4Copy));
System.out.println("- Call flush..");
// This time have Insert or Update to DB. (!!!)
session.flush();
// 'tk4' still Transitent, after flush().
// merge(..) safer than saveOrUpdate().
System.out.println("- tk4 Persistent? " + session.contains(tk4));
//
String timekeeperId = tk4.getTimekeeperId();
System.out.println("- timekeeperId = " + timekeeperId);
System.out.println("- inOut = " + tk4.getInOut());
System.out.println("- dateTime = " + df.format(tk4.getDateTime()));
System.out.println();
return tk4;
}
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
Employee emp = null;
try {
session.getTransaction().begin();
emp = DataUtils.findEmployee(session, "E7499");
saveOrUpdate_Transient(session, emp);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Persistent --> Detached
Un objet de l'état Persistent (Géré par Hibernate) peut changer de l'état Detached (Détaché, ne pas être géré par Hibernate) via la méthode ci-dessous de Session :
- evict(Object)
Expulser un objet en dehors de la gestion de Hibernate
- clear()
Expulser tous les objets en dehors de la gestion de Hibernate.
Remarque : Lors que l'objet Session appelle une des méthodes: commit(), close(), rollback() la session terminera. Tous les objets Persistence de cette session seront considérés Detached avec un nouveau session.
EvictDemo.java
package org.o7planning.tutorial.hibernate.demo;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class EvictDemo {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
Employee emp = null;
try {
session.getTransaction().begin();
// This is object has Persistent status
emp = DataUtils.findEmployee(session, "E7499");
// ==> true
System.out.println("- emp Persistent? " + session.contains(emp));
// using evict() to evicts a single object from the session
session.evict(emp);
// Now 'emp' has Detached status
// ==> false
System.out.println("- emp Persistent? " + session.contains(emp));
// All change on the 'emp' will not update
// if not reatach 'emp' to session
emp.setEmpNo("NEW");
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
ClearDemo.java
package org.o7planning.tutorial.hibernate.demo;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Department;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class ClearDemo {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
Employee emp = null;
Department dept = null;
try {
session.getTransaction().begin();
// It is an object has Persistent status.
emp = DataUtils.findEmployee(session, "E7499");
dept = DataUtils.findDepartment(session, "D10");
// clear() evicts all the objects in the session.
session.clear();
// Now 'emp' & 'dept' has Detached status
// ==> false
System.out.println("- emp Persistent? " + session.contains(emp));
System.out.println("- dept Persistent? " + session.contains(dept));
// All change on the 'emp' will not update
// if not reatach 'emp' to session
emp.setEmpNo("NEW");
dept = DataUtils.findDepartment(session, "D20");
System.out.println("Dept Name = "+ dept.getDeptName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Detached --> Persistent : Vue d'ensemble
Un objet de l'état Detached (détaché de la gestion de Hibernate) peut être rattaché (Re-attach) via quelques méthodes de Session :
- update(Object)
- saveOrUpdate(Object)
- merge(Object)
- refresh(Object)
- lock(Object)
Observez les exemples ci-dessous pour voir la différence entre des méthodes :
Detached --> Persistent : L'utilisation update(Object)
UpdateDetachedDemo.java
package org.o7planning.tutorial.hibernate.demo;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class UpdateDetachedDemo {
public static void main(String[] args) {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session1 = factory.getCurrentSession();
Employee emp = null;
try {
session1.getTransaction().begin();
// This is a Persistent object.
emp = DataUtils.findEmployee(session1, "E7499");
// session1 was closed after a commit is called.
session1.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session1.getTransaction().rollback();
}
// Open other session
Session session2 = factory.getCurrentSession();
try {
session2.getTransaction().begin();
// Check state of 'emp'
// ==> false
System.out.println("- emp Persistent? " + session2.contains(emp));
System.out.println("Emp salary: " + emp.getSalary());
emp.setSalary(emp.getSalary() + 100);
// update (..) is only used for Detached object.
// (Not for Transient object).
// Use the update (emp) to bring back emp Persistent state.
session2.update(emp);
// Call flush
// Update statement will be called.
session2.flush();
System.out.println("Emp salary after update: " + emp.getSalary());
// session2 was closed after a commit is called.
session2.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session2.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Detached --> Persistent : L'utilisation saveOrUpdate(Object)
SaveOrUpdateDetachedDemo.java
package org.o7planning.tutorial.hibernate.demo;
import java.util.Random;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class SaveOrUpdateDetachedDemo {
public static void main(String[] args) {
// An object Detached state.
Employee emp = getEmployee_Detached();
System.out.println(" - GET EMP " + emp.getEmpId());
// Random delete or not delete Employee
boolean delete = deleteOrNotDelete(emp.getEmpId());
System.out.println(" - DELETE? " + delete);
// Call saveOrUpdate for detached object.
saveOrUpdate_test(emp);
// After call saveOrUpdate()
System.out.println(" - EMP ID " + emp.getEmpId());
}
// Return Employee object has Detached state
private static Employee getEmployee_Detached() {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session1 = factory.getCurrentSession();
Employee emp = null;
try {
session1.getTransaction().begin();
Long maxEmpId = DataUtils.getMaxEmpId(session1);
System.out.println(" - Max Emp ID " + maxEmpId);
Employee emp2 = DataUtils.findEmployee(session1, "E7839");
Long empId = maxEmpId + 1;
emp = new Employee();
emp.setEmpId(empId);
emp.setEmpNo("E" + empId);
emp.setDepartment(emp2.getDepartment());
emp.setEmpName(emp2.getEmpName());
emp.setHideDate(emp2.getHideDate());
emp.setJob("Test");
emp.setSalary(1000F);
// emp has been managed by Hibernate
session1.persist(emp);
// session1 was closed after a commit is called.
// An Employee record are insert into DB.
session1.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session1.getTransaction().rollback();
}
// Session1 closed 'emp' switch to Detached state.
return emp;
}
// Random: delete or not delete.
private static boolean deleteOrNotDelete(Long empId) {
// A random number 0-9
int random = new Random().nextInt(10);
if (random < 5) {
return false;
}
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session2 = factory.getCurrentSession();
try {
session2.getTransaction().begin();
String sql = "Delete " + Employee.class.getName() + " e "
+ " where e.empId =:empId ";
Query query = session2.createQuery(sql);
query.setParameter("empId", empId);
query.executeUpdate();
session2.getTransaction().commit();
return true;
} catch (Exception e) {
e.printStackTrace();
session2.getTransaction().rollback();
return false;
}
}
private static void saveOrUpdate_test(Employee emp) {
SessionFactory factory = HibernateUtils.getSessionFactory();
// Open other session
Session session3 = factory.getCurrentSession();
try {
session3.getTransaction().begin();
// Check state of emp
// ==> false
System.out.println(" - emp Persistent? " + session3.contains(emp));
System.out.println(" - Emp salary before update: "
+ emp.getSalary());
// Set new salary for Detached emp object.
emp.setSalary(emp.getSalary() + 100);
// Using saveOrUpdate(emp) to switch emp to Persistent state
// Note: If exists object same ID in session, this method raise Exception
//
// Now, no action with DB.
session3.saveOrUpdate(emp);
// By pushing data into the DB.
// It will call a Insert or update statement.
// If the record is deleted before ==> insert
// Else ==> update.
session3.flush();
System.out
.println(" - Emp salary after update: " + emp.getSalary());
// session3 was closed after a commit is called.
session3.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session3.getTransaction().rollback();
}
}
}
Exécutez l'exemple ci-dessous quelques fois, vous pouvez trouver deux situations, saveOrUpdatecrée des actions: Insert ou Update dans la DB.
INSERT:
UPDATE:
Detached --> Persistent : L'utilisation merge(Object)
Hibernate version 2 a deux méthodes saveOrUpdateCopy(Object). À partir de la 3ème version, il adopte le nouveau nom merge(Object). Donc mergea certaines ressemblances et différences par rapport à saveOrUpdate.merge(Object) ne met pas objet sous la gestion de Hibernate, mais il crée une copie de l'objet et il gère l'objet à copier.Si vous appelez saveOrUpdate(aObject) alors que bObject est géré sous la gestion de Hibernate et a le même ID avec aObject une exception sera lancée. Lors que vous utilisez le merge(aObject) il n'y a pas cette exception.
MergeDetachedDemo.java
package org.o7planning.tutorial.hibernate.demo;
import java.util.Random;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class MergeDetachedDemo {
public static void main(String[] args) {
// An object has Detached status
Employee emp = getEmployee_Detached();
System.out.println(" - GET EMP " + emp.getEmpId());
// Random: delete or not delete the Employee by ID.
boolean delete = deleteOrNotDelete(emp.getEmpId());
System.out.println(" - DELETE? " + delete);
// Call saveOrUpdate Detached object
saveOrUpdate_test(emp);
// After call saveOrUpdate
// ...
System.out.println(" - EMP ID " + emp.getEmpId());
}
// Method return Employee object
// and has Detached status.
private static Employee getEmployee_Detached() {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session1 = factory.getCurrentSession();
Employee emp = null;
try {
session1.getTransaction().begin();
Long maxEmpId = DataUtils.getMaxEmpId(session1);
System.out.println(" - Max Emp ID " + maxEmpId);
Employee emp2 = DataUtils.findEmployee(session1, "E7839");
Long empId = maxEmpId + 1;
emp = new Employee();
emp.setEmpId(empId);
emp.setEmpNo("E" + empId);
emp.setDepartment(emp2.getDepartment());
emp.setEmpName(emp2.getEmpName());
emp.setHideDate(emp2.getHideDate());
emp.setJob("Test");
emp.setSalary(1000F);
// 'emp' has Persistant state
session1.persist(emp);
// session1 was closed after a commit is called.
// An Employee record are insert into DB.
session1.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session1.getTransaction().rollback();
}
// session1 closed, 'emp' switched Detached state.
return emp;
}
// Delete Employee by ID
// Random: delete or not delete
private static boolean deleteOrNotDelete(Long empId) {
// A random number 0-9
int random = new Random().nextInt(10);
if (random < 5) {
return false;
}
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session2 = factory.getCurrentSession();
try {
session2.getTransaction().begin();
String sql = "Delete " + Employee.class.getName() + " e "
+ " where e.empId =:empId ";
Query query = session2.createQuery(sql);
query.setParameter("empId", empId);
query.executeUpdate();
session2.getTransaction().commit();
return true;
} catch (Exception e) {
e.printStackTrace();
session2.getTransaction().rollback();
return false;
}
}
private static void saveOrUpdate_test(Employee emp) {
SessionFactory factory = HibernateUtils.getSessionFactory();
// Open other session
Session session3 = factory.getCurrentSession();
try {
session3.getTransaction().begin();
// The fact, 'emp' has Detached state
// It is not managed by Hibernate.
// Check the status of emp:
// ==> false
System.out.println(" - emp Persistent? " + session3.contains(emp));
System.out.println(" - Emp salary before update: "
+ emp.getSalary());
// Set new salary for Detached object 'emp'
emp.setSalary(emp.getSalary() + 100);
// merge(emp) return empMerge, a copy of 'emp',
// empMerge managed by Hibernate
// 'emp' still in Detached state
//
// At this time there is no action regarding DB.
Employee empMerge = (Employee) session3.merge(emp);
// ==> false
System.out.println(" - emp Persistent? " + session3.contains(emp));
// ==> true
System.out.println(" - empMerge Persistent? "
+ session3.contains(empMerge));
// Push data into the DB.
// Here it is possible to create the Insert or Update on DB.
// If the corresponding record has been deleted by someone, it insert
// else it update
session3.flush();
System.out
.println(" - Emp salary after update: " + emp.getSalary());
// session3 closed after a commit is called.
session3.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session3.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
INSERT:
UPDATE:
Detached --> Persistent : L'utilisation refresh(Object)
RefreshDetachedDemo.java
package org.o7planning.tutorial.hibernate.demo;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
public class RefreshDetachedDemo {
public static void main(String[] args) {
// an Object with Detached status
Employee emp = getEmployee_Detached();
System.out.println(" - GET EMP " + emp.getEmpId());
// Refresh Object
refresh_test(emp);
}
// Return Employee object has Detached state
private static Employee getEmployee_Detached() {
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session1 = factory.getCurrentSession();
Employee emp = null;
try {
session1.getTransaction().begin();
emp = DataUtils.findEmployee(session1, "E7839");
// session1 was closed after a commit is called.
// An Employee record are insert into DB.
session1.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session1.getTransaction().rollback();
}
// Session1 closed 'emp' switch to Detached state.
return emp;
}
private static void refresh_test(Employee emp) {
SessionFactory factory = HibernateUtils.getSessionFactory();
// Open other session
Session session2 = factory.getCurrentSession();
try {
session2.getTransaction().begin();
// Check the status of 'emp' (Detached)
// ==> false
System.out.println(" - emp Persistent? " + session2.contains(emp));
System.out.println(" - Emp salary before update: "
+ emp.getSalary());
// Set new salary for 'emp'.
emp.setSalary(emp.getSalary() + 100);
// refresh: make a query statement
// and switch 'emp' to Persistent state
// The changes are ignored
session2.refresh(emp);
// ==> true
System.out.println(" - emp Persistent? " + session2.contains(emp));
System.out.println(" - Emp salary after refresh: "
+ emp.getSalary());
session2.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session2.getTransaction().rollback();
}
}
}
Les résultats d'exécution de l'exemple :
Detached --> Persistent : Using lock(Object)
- TODO...
Tutoriels Java Hibernate
- Référence Java Hibernate
- Installer JBoss Tools pour Eclipse
- Utiliser les outils Hibernate pour générer des classes Entity à partir de tables
- Générer des tables à partir de classes Entity dans Hibernate
- La pagination s’effectue en Java Hibernate
- Le Tutoriel de Java Hibernate
Show More