JavaJEEJPA: Difference between revisions

From Wiki RB4
Line 175: Line 175:


  CriteriaQuery<T> c = qb.createQuery(T.class);
  CriteriaQuery<T> c = qb.createQuery(T.class);
CriteriaQuerys are the nodes that are assembled in a tree to specify a CriteriaQuery. The generic type argument declares the type of result this CriteriaQuery will return upon execution.
'''CriteriaQuerys''' are the nodes that are assembled in a tree to specify a CriteriaQuery. The generic type argument declares the type of result this CriteriaQuery will return upon execution.


  Root<T> p = c.from(T.class);
  Root<T> p = c.from(T.class);
Sets CriteriaQuery to query from T and returns the root of the query expression. The ctor means e''valuate the expression across all instances of T''. It is like the FROM clause of an SQL statement.
Sets CriteriaQuery to query from T and returns the root of the query expression. The ctor means e''valuate the expression across all instances of T''. It is like the FROM clause of an SQL statement.
Predicate condition = qb.eq(....);
c.where(condition);
Predicate is another common form of query expression that evaluates to either true or false. A predicate is constructed by the CriteriaBuilder, which is the factory not only for CriteriaQuery, but also for query expressions.


=Performance=
=Performance=

Revision as of 22:46, 21 January 2012

Introduction

The Java Persistence API originated as part of the work of the JSR 220 Expert Group. JPA 2.0 is the work of the JSR 317 Expert Group. The final release date of the JPA 1.0 specification was 11 May 2006. The JPA 2.0 specification was released 10 Dec, 2009. JPA is a replacement for the much criticized EJB 2.0 and EJB 2.1 entity beans.

The easiest way is to use annotations. To search for entities there is JPQL. The API defines the interface and is no persistence provider. This is for example JBoss or Glassfish.

Implementations

Hibernate Versions 3.2 and later provide an implementation for the Java Persistence API.

Entity Manager

The central instance of the JPA is the entity manager (persistence manager) (interface javax.persistence.EntityManager), which is provided by the persistence provider. The entity manager is responsible for

  • erstmaliges persist an object
  • merge of an object state with the state in the database, detached objects werden wieder vom entity manager verwaltet
  • remove an object from the database
  • find an enitity by primary key or query by JPQL
  • lock an entity
  • flush the persistence context
  • close the entity manager.

Entities

An entity can have different states:

  • transient (created by new(), no associated row in database)
  • persistent (has an database identity, are associated with a persistence context)
  • removed (by remove())
  • detached (lived on over a transaction)

Entity Identity

For composite keys you have three options:

  1. encapsulate the identifier properties in a separate class and mark it as @Embeddable. Include an attribute of this class in the entity class an mark it with @Id
  2. encapsulale the identifier properties in a separate class without annotation, include an attribute of this class in the entity class and mark it with @EmbeddedId
  3. @IdClass

Persistance Context

The entity manager provides a persistence context. The persistance context contains all entities managed by a specific entity manager. The entity manager is accessed via JNDI or in an EJB container by injection (javax.persistence.PeristenceContext).

Persistance Unit

A persistence unit is the group of classes which is managed by one entity manager and references one database. It also indicates which transaction type is to be used when the database operations occur. The persistence unit consists of three main parts.

  • entity metadata
  • persistence unit descriptor
    • persistence provider
    • database connection
    • transaction type
  • persistence manager factory

A persistence unit is defined in persistence.xml.

Configuration

persistence.xml

  • in case of WAR file WEB-INF/classes/META-INF, in case of EAR file META-INF directory of the beans jar file
<persistence>
  <persistence-unit name="<Name>" [transaction-type= > // s. annotation PersistenceContext
    <provider></provider>
    <jta-data-source>java:/<Name></jta-data-source> // points to a name of a data source configuration s. JBoss Database configuration
    <provider>
      <property> </property>
    </provider>
  </persistence-unit>
</persistence>

orm.xml

If annotations are not used then the object relational mapping is declared in META-INF/orm.xml.

Annotations

The location of the annotations e.g. before the attributes/fields or before the methods is important.

  1. Access to attributes: JPA allows for two types of access to the data of a persistent class, field/property access or method access. What access type it will be used is decided by where you put the @Id annotation (on the id field or the getId() method). Which type to use depends on: performance (reflection is faster?), logic inside the getter and/or setter, validation, independent refactoring, exception handling (see. Java Persistance with Hibernate, 3.25).
  2. Names of the db columns: Field access which means that it maps the instance variables (fields) to columns in the database and Property access which means that is uses the getters to determine the property names that will be mapped to the db.

javax.persistence.AttributesOverrides

@EmbeddedId
@AttributeOverrides( {
  @AttributeOverride(name = "kategorieId", column = @Column(name = "kategorie_id", nullable = false)),
  @AttributeOverride(name = "sprachId", column = @Column(name = "sprach_id", nullable = false)) })

Only make sense with the Embedded Annotations to override specifications for the embedded class.


javax.persistence.Basic

@javax.persistence.Basic([fetch=(FetchType.EAGER|FetchType.LAZY)])
<method declaration>

The Basic annotation maps the java type to a database type. It is standard and has to be used seldomly. It can be used to specify the fetch strategy. Normally all attributes are fetched while loading the entity. Lazy delays it to the first use.

javax.persistence.Column

@javax.persistence.Column[([name="<Name>"])]
<attribute declaration>


javax.persistence.Entity

  • if no table specified, tablename is classname
  • all members are persistent, unless speficied with javax.persistence.Transient

java.persistence.GeneratedValue

javax.persistence.Id

A primary key:

  • should never be null
  • should unique
  • should never change.

javax.persistence.Lob

@javax.persistence.Lob
<method declaration>
  • large object for large data
  • the concrete type is derived from the java datatype

javax.persistence.PersistenceContext

works if the client is running inside a persistance provider.

@javax.persistence.PersistenceContext[([type=(TRANSACTION|EXTENDED)][,][unitName="<Name>"])]
private javax.persistence.EntityManager <attribute name>;

injection via

@javax.persistence.PersistenceContext(unitName="testejbapplication") // s. persistence.xml <persistence-unit>
private javax.persistence.EntityManager em;
  • default type TRANSACTION: persistence context is closed after transaction, all persistence entities are detached
  • type EXTENDED: starts with creating entity manager and end when it is destroyed, that is e.g. for the lifetime of a SFSB
  • object state is synchronized with database without persist() or merge() call

javax.persistance.Table

@javax.persistance.Table[([name="<Name>"])]
<class declaration>

javax.persistance.Temporal

@javax.persistance.Temporal[(TemporalType.DATE|TemporalType.TIME|TemporalType.TIMESTAMP)]
<method declaration>

Specifies the database type for the java type java.util.Date or java.util.Calendar.

Java Persistence Query Language (JPQL)

JPQL is an extension of EJBQL, which was introduced as part of the EJB 2.0 specification. The query language allows you to write portable queries that work regardless of the underlying data store. Queries in JPQL are not like SQL queries. Where a SQL query deals with tables and columns, a JPQL query deals with objects and attributes. Keywords of JPQL are case-insensitve, entities, identifier, attributes are case-sensitive. Operators are:

  • OR
  • AND
  • <>
  • NOT
  • BETWEEN
  • LIKE
  • IN
  • EMPTY
  • IS NULL
  • WHERE

Examples

s. also http://edocs.bea.com/kodo/docs41/full/html/ejb3_overview_query.html#ejb3_query_api

Query q = em.createQuery(<QUERYSTRING>);
Query q = em.createNamedQuery(<QUERYNAME>); // see @NamedQueries annotation
List<Type> l = q.getResultList();


// Query Strings
select (Object()<Identifier>()) from <EntityName> (as) <Identifier>
SELECT k FROM Kategorien k // Kategorien is the classname
SELECT k FROM Kategorien k WHERE k.id.kategorieId = 1006 // id is a composite key
SELECT x FROM Magazine x WHERE x.y.z = 'abc' OR x.y IS NULL
SELECT x FROM Magazine x, IN(x.articles) y WHERE y.author = 'Mister B'
SELECT kadisId, productsOptionsValuesName FROM ballaballa.dbxt.ProductsOptionsValues p
Query q = emXT.createQuery("SELECT MAX(pov.id.productsOptionsValuesId) + 1 FROM ballaballa.dbxt.ProductsOptionsValues pov");
Number newPovIdNumber = (Number)q.getSingleResult();
Query q = emXT.createQuery("DELETE pa FROM ballaballa.dbxt.Produktattribute pa WHERE pa.id.hauptartikelnummer < " + BallaballaProperties.getHandmadeProductsMinKadisID());
q.executeUpdate();

q = emXT.createNativeQuery("INSERT INTO xt_sport_boeckmann.produktattribute " + " (`hauptartikelnummer`, `bestand`, `farbe_id`, `groesse_id`, `variantennummer`, `sortier_position`, `veroeffentlichungsdatum`,`verfuegbar_ab`) SELECT `hauptartikelnummer`,`bestand`,`farbe_id`,`groesse_id`,`variantennummer`,`sortier_position`,`veroeffentlichungsdatum`,`verfuegbar_ab` FROM " + " sp_kadis_db.produktattribute");
q.executeUpdate();

Type-safe Querying

CriteriaQuery<T> c = qb.createQuery(T.class);

CriteriaQuerys are the nodes that are assembled in a tree to specify a CriteriaQuery. The generic type argument declares the type of result this CriteriaQuery will return upon execution.

Root<T> p = c.from(T.class);

Sets CriteriaQuery to query from T and returns the root of the query expression. The ctor means evaluate the expression across all instances of T. It is like the FROM clause of an SQL statement.

Predicate condition = qb.eq(....);
c.where(condition);

Predicate is another common form of query expression that evaluates to either true or false. A predicate is constructed by the CriteriaBuilder, which is the factory not only for CriteriaQuery, but also for query expressions.

Performance

  1. s. tips here

Dynamics

Make an entity persistent

Item i = new Item();
i.set(a);
transaction = entityManager.getTransaction();
transaction.begin();	
entityManager.persist(i);
transaction.commit();
entityManager.close();

Find an entity by its id

Item i = em.find(Item.class, new Long(1111));

Saving entities

JPA keeps an eye on the changes of an persistent object. An explicit save() is not neccessary. The so called flushing happens whenever a commit() is called. However, JPA implementations are allowed to synchronize at other times. E.g. Hibernate synchronize additionally (this is configurable):

  • before a query is called
  • when em.flush() is called.

Resources