JPA provides developers with an ORM facility for managing relational data. JPA consists of 4 areas:
The Java Persistence API
The query language
The Criteria API
ORM metadata
https://docs.oracle.com/javaee/7/tutorial/persistence-intro.htm
-
Java DataBase Connectivity
-
API d’accès aux bases de données SQL
-
Code indépendant du type de la base de données
-
Nécessite l’écriture de code SQL
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost/test", "user", "password");
PreparedStatement stmt = connection.prepareStatement(
"SELECT * FROM PERSON WHERE ID = ?");
stmt.setString(1, 1234L);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
String name = rs.getString("NAME");
Date birthDate = rs.getDate("BIRTH_DATE");
Person person = new Person(name, birthDate);
}
if (conn != null) {
conn.close();
}
- Point à point
-
Gestionnaire de pilotes
- Ressource commune
-
Source de données
-
Inadapté pour un nombre élevé de connections
-
Dépassement du nombre de connections côté DB
-
Refus de nouvelles connections après une certaine limite
-
-
Temps d’ouverture d’une nouvelle connection
-
Pour un nombre élevé de connections utilisées pour une courte durée
-
Pool de connections initialisées au démarrage du serveur d’applications
-
Récupérer une connection de la source de données
-
Utiliser la connection pour exécuter du code SQL
-
Remettre la connection à disposition du pool
-
Appel de la méthode
close()
-
-
Paramètres : URL de la base, nombre initial de connections, nombre maximal, etc.
-
Dépendant du serveur d’applications
-
Mis à disposition dans l’arbre de ressources JNDI
-
Code explicite pour récupérer la ressource JNDI
-
Injection via
@Resource
-
Configuration pour JPA
public class SomeRepository {
@Resource(name="java:comp/env.jdbc/mydb")
private DataSource dataSource;
...
}
An entity is a lightweight persistence domain object. An entity class represents a table in a relational database, and each entity instance corresponds to a row in that table.
-
Etre annotée avec
@javax.persistence.Entity
-
Respecter le contrat d’un JavaBean
-
Constructeur
public
sans argument -
Accesseurs publics
-
-
Avoir un attribut/getter d’id
-
Types primitifs
-
Chaînes de caractères
-
Types
Serializable
-
Enumérations
-
Entités
-
Collections des types ci-dessus
- Auto-incrémentation
-
GenerationType.IDENTITY
- Séquence
-
-
GenerationType.SEQUENCE
-
@SequenceGenerator
-
- Table
-
-
GenerationType.TABLE
-
@TableGenerator
-
@Entity
public class Book {
@Id @GeneratedValue(strategy=IDENTITY)
private long id;
private String isbn;
private String title;
private String description;
private Date publicationDate;
private Author author;
// Getters and setters
}
-
Par défaut :
- Nom de l’entité
-
nom de la table
- Nom de l’attribut
-
nom de la colonne
-
@javax.persistence.Table(name = "PERSON")
-
@javax.persistence.Column(name = "FIRST_NAME")
Les annotations précédentes permettent également :
-
Spécification d’un schéma
-
Définition des contraintes (DDL)
@Entity
@Table(name="T_BOOK")
public class Book {
@Id @GeneratedValue(strategy=IDENTITY)
private long id;
private String isbn;
private String title;
private String description;
@Column(name="PUBLICATION_DATE")
private Date publicationDate;
private Author author;
// Getters and setters
}
The EntityManager API creates and removes persistent entity instances, finds entities by the entity’s primary key, and allows queries to be run on entities.
-
Gestion du cycle de vie
-
Recherche d’une entité par sa clé primaire
-
Synchronisation avec la base de données
-
Exécution de requêtes avec l’API Criteria
-
Exécution de requêtes JPQL (& SQL)
-
etc.
-
Initialisé par le serveur d’apps
-
Fichier
persistence.xml
-
Situé dans
WEB-INF/classes/META-INF
<persistence>
<persistence-unit name="PeopleManagement">
<!-- Non-default data source
<jta-data-source>jdbc/people</jta-data-source>
-->
<class>ch.frankel.Person</class>
<class>ch.frankel.Teacher</class>
<class>ch.frankel.Student</class>
</persistence-unit>
</persistence>
@Stateless
public class Service {
@PersistenceContext
private EntityManager em;
}
A transaction symbolizes a unit of work performed within a DBMS against a database, and treated in a coherent and reliable way independent of other transactions.
transaction.begin();
em.persist(new Person());
transaction.commit();
@Stateless
public class Service {
@Resource
private UserTransaction userTransaction;
}
@Stateless
public class Service {
@Transactional
public void doInTransaction() {
// Everything here will run in a transaction
}
}
-
Commit à la fin de la méthode pour une exécution normale
-
En cas d’exception
runtime
, rollback -
@Transactional(rollbackFor=MyException.class)
-
Permet les transactions distribuées
-
2-Phases Commit
-
-
Nécessite un pilote JDBC XA
An EJB component is a body of code that has fields and methods to implement modules of business logic.
@Stateless
public class AccountService {
@Transactional
public void transfer(Account source, Account target, Money amount) {
// Business logic
}
}
The query language allows you to write portable queries that work regardless of the underlying data store. It uses the abstract persistence schemas of entities, including their relationships, for its data model and defines operators and expressions based on this data model.
http://bit.ly/2jbjNft
PreparedStatement stmt = conn.prepareStatement(
"SELECT * FROM PERSON " +
"WHERE FIRST_NAME LIKE ? AND LAST_NAME LIKE ?");
stmt.setString(1, firstName);
stmt.setString(2, lastName);
ResultSet rs = stmt.executeQuery();
The Criteria API is used to define queries for entities and their persistent state by creating query-defining objects. Criteria queries are written using Java programming language APIs, are typesafe, and are portable
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
cq.from(Person.class);
TypedQuery<Person> q = em.createQuery(cq);
List<Person> allPersons = q.getResultList();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> person = cq.from(Person.class);
cq.where(cb.like(person.get("firstName"), firstName),
cb.like(person.get("lastName"), lastName));
TypedQuery<Person> q = em.createQuery(cq);
List<Person> persons = q.getResultList();
For each entity class in a particular package, a metamodel class is created with a trailing underscore and with attributes that correspond to the persistent fields or properties of the entity class.
-
Soit :
-
Manuelle
-
Via l’implémentation spécifique
-
-
Devrait être synchronisée avec chaque changement de code
-
Via un outil de build (Maven)
-
javac -classpath $TOMEE_HOME/lib/openjpa-3.1.0.jar:\
$TOMEE_HOME/lib/javaee-api-8.0-3.jar \
-Aopenjpa.metamodel=true \
-Aopenjpa.source=8 ch/hesge/javaee/Book.java
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> person = cq.from(Person.class);
cq.where(cb.like(person.get(Person_.firstName), firstName),
cb.like(person.get(Person_.lastName), lastName));
TypedQuery<Person> q = em.createQuery(cq);
List<Person> persons = q.getResultList();