Showing posts with label JPA. Show all posts
Showing posts with label JPA. Show all posts

Sunday, 11 November 2012

Introduction To Spring JPA Data Features

This post is a quick introduction to Spring JPA Data's (SJD) features. This Spring module is built on top of the Spring Data Commons module, which is a prerequisite read in order to understand this post.

Features

This module offers several features:
  • JpaRepository<T, ID extends Serializable> - This interface extends the CrudRepository and PageAndSortingRepository interfaces of the Spring Data Commons module. It offers a couple of extra flush, find all and delete operations. See here for an operational example.
  • JPA Query Methods - This is a powerful mechanism allowing Spring to create queries from method names in classes/interfaces implementing Repository. For example: List<Invoice> findByStartDateAfter(Date date); is automatically translated into select i from Invoice i where u.startDate > ?1.
  • @Query - Queries can be associated to methods in Repository classes/interfaces. For example, a method can be annotated with @Query("select i from Invoice i where u.startDate > ?1")
  • @Modifying - This annotation can be used in combination with @Query to indicate that the corresponding query will perform modifications. Hence, any outdated entities are cleared first.
  • @Lock - This annotation is used to set the lock mode type (none, optimistic, pessimistic, etc...) for a given @Query.
  • JpaSpecificationExecutor and Specification - This interface adds a couple find and count of methods to repository classes/interfaces. All, have a Specification  parameter, which add predicates (i.e., where clauses) to corresponding queries.
  • Auditable, AbstractPersistable and AbstractAuaditable - The Auditable interface allows one to track modifications made to an entity (creation, last modification...). The AbstractPersistable and AbstractAuditable are abstract class facilities avoiding the boilerplate code.
  • MergingPersistenceUnitManager - If a developer decides to modularize his/her application, he/she may still want to use a unique persistence unit, even though they are declared in separate XML file. The MergingPersistenceUnitManager solves this issue.
At last, to enable JPA repositories, the:

    @EnableJpaRepositories("com.my.repositories")

should be set on a Java @Configuration class.

More Spring related posts here.

Tuesday, 11 September 2012

Select From JPA Criteria API Example

This post describes how to generate Select From queries using the JPA Criteria API. All code examples are available from Github in the JPA directory. Some error messages will be displayed when running some examples because of a known and harmless issue.

This code example relies on a simple item:
@Entity
@AutoProperty
public class SomeItem {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long Id;

    private String data;

    // Constructors, Setters & Getters, Pojomatic...

}
The following code creates and executes a simple Select From query using the JPA Criteria API:
// Creating some data
SomeItem A = new SomeItem("rttt");
SomeItem B = new SomeItem("qqqq");
SomeItem C = new SomeItem("zzzz");

JPA.INSTANCE.save(A);
JPA.INSTANCE.save(B);
JPA.INSTANCE.save(C);

CriteriaBuilder cb = JPA.INSTANCE.EM.getCriteriaBuilder();

// Constructing Select * from SomeItem
CriteriaQuery<SomeItem> q = cb.createQuery(SomeItem.class);
Root<SomeItem> c = q.from(SomeItem.class);
q.select(c);

// Executing the query
TypedQuery<SomeItem> query = JPA.INSTANCE.EM.createQuery(q);
List<SomeItem> results = query.getResultList();

// Printing results
for ( SomeItem si : results ) {
    System.out.println(si);
}
The generated output is:
SomeItem{Id: {1}, data: {rttt}}
SomeItem{Id: {2}, data: {qqqq}}
SomeItem{Id: {3}, data: {zzzz}}
More about query parameters here.

Tuesday, 4 September 2012

JUnit Testing Spring Service and DAO (with In-Memory Database)

This post describes how to implement JUnit tests for a Spring Web Application's Services and DAO. It is built on top of the Spring MVC-Service-DAO-Persistence Architecture Example. This example is available from Github in the Spring-Web-JPA-Testing directory.

Reminder

  • Test Fixture - The fixed state used as a baseline for running tests.
  • Unit test - These tests verify that pieces of code (components) perform some functionalities as expected. In a Java environment, these are typically implemented at the class level.
  • Integration test - Integration testing is any type of test checking that a set of interacting components perform expected functionalities together correctly.

Configuration

We need a JPA Hibernate configuration for in-memory testing:
@Configuration
@EnableTransactionManagement
public class JpaTestConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){

        LocalContainerEntityManagerFactoryBean lcemfb
            = new LocalContainerEntityManagerFactoryBean();

        lcemfb.setDataSource(this.dataSource());
        lcemfb.setPackagesToScan(new String[] {"com.jverstry"});
        lcemfb.setPersistenceUnitName("MyTestPU");

        HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
        lcemfb.setJpaVendorAdapter(va);

        Properties ps = new Properties();
        ps.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
        ps.put("hibernate.hbm2ddl.auto", "create");
        lcemfb.setJpaProperties(ps);

        lcemfb.afterPropertiesSet();

        return lcemfb;

    }

    @Bean
    public DataSource dataSource(){

        DriverManagerDataSource ds = new DriverManagerDataSource();

        ds.setDriverClassName("org.hsqldb.jdbcDriver");
        ds.setUrl("jdbc:hsqldb:mem:testdb");
        ds.setUsername("sa");
        ds.setPassword("");

        return ds;

    }

    @Bean
    public PlatformTransactionManager transactionManager(){

        JpaTransactionManager tm = new JpaTransactionManager();

        tm.setEntityManagerFactory(
            this.entityManagerFactoryBean().getObject() );

        return tm;

    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
        return new PersistenceExceptionTranslationPostProcessor();
    }

}
We need to exclude the production configuration from package scanning (no "com.jverstry" scanning):
@Configuration
@ComponentScan(basePackages = {
    "com.jverstry.Controller",
    "com.jverstry.DAO",
    "com.jverstry.Item",
    "com.jverstry.Service"
})

public class TestConfig {

    @Bean
    public MyService getMyService() {
        return new MyServiceImpl();
    }

}

Spring Testing Tools

  • @RunWith - This is a JUnit annotation allowing one to run a test with a different runner than the one provided by JUnit.
  • SpringJUnit4ClassRunner - This is a JUnit test runner for Spring applications. Typically, test classes are annoted with @RunWith(SpringJUnit4ClassRunner.class)
  • @ContextConfiguration - This annotation can be used to specify how to load an applicationContext in Spring test class. This can be configured via XML files or Java configuration objects.

Service Testing

The following class tests the createAndRetrieve() method of our injected MyService implementation:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ JpaTestConfig.class, TestConfig.class })
public class MyServiceImplTest {

    @Autowired
    private MyService myService;

    @Test
    public void testCreateAndRetrieve() {

        MilliTimeItem retr = myService.createAndRetrieve();

        assertNotNull(retr);

    }

}

DAO Testing

The following class tests our DAO implementation. Our implementation is injected with an EntityManager created from our test configuration class defined above.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ JpaTestConfig.class, TestConfig.class })
public class MyPersistenceDAOTest {

    @Autowired
    private MyPersistenceDAO myDAO;

    @Test
    public void testCreateMilliTimeItem() {

        // This operation should not throw an Exception
        long id = myDAO.createMilliTimeItem();

    }

    @Test
    public void testGetMilliTimeItem() {

        long id = myDAO.createMilliTimeItem();
        MilliTimeItem retr = myDAO.getMilliTimeItem(id);

        assertNotNull(retr);
        assertEquals(id,retr.getID());

    }

}

Caveat

When starting to write JUnit tests for Spring, one can come across the following error messages:
Java.lang.ClassFormatError:
Absent Code attribute in method that is not native or abstract in class file javax/validation/Validation
The above is often caused by the following maven dependency:
         <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>6.0</version>
            <type>jar</type>
         </dependency>
It should be replaced with:
           <dependency>
               <groupId>org.apache.geronimo.specs</groupId>
               <artifactId>geronimo-jpa_2.0_spec</artifactId>
               <version>1.1</version>
               <scope>provided</scope>
           </dependency>
Another error message is:
javax.validation.ValidationException: Unable to find a default provider
This is solved by adding the following maven dependency:
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.3.0.Final</version>
        </dependency>

For Spring MVC Controller JUnit testing, see here • More Spring related posts here.

Monday, 3 September 2012

Spring Web JPA Hibernate In-Memory Example

This post introduces the web version of the Standalone Hibernate JPA In-Memory example. It relies on a very simple implementation of the Spring MVC framework. This example is available from Github in the Spring-Web-JPA-Roundtrip directory.

Configuration

Instead of using the traditional JPA persistence.xml configuration file, we use Java configuration. On top of the traditional WebConfig class, we have a JpaConfig class annotated with @EnableTransactionManagement to enable database transactions.

The LocalContainerEntityManagerFactoryBean is the easiest mean to configure JPA. Notice that the persistence.xml database connection information is moved to the DataSource. The PlatformTransactionManager is required to process @Transactional annotated method (discussed further).

PersistenceExceptionTranslationPostProcessor converts any vendor specific exceptions into Spring DataAccessException for easier handling.
@Configuration
@EnableTransactionManagement
public class JpaConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){

        LocalContainerEntityManagerFactoryBean lcemfb
            = new LocalContainerEntityManagerFactoryBean();

        lcemfb.setDataSource(this.dataSource());
        lcemfb.setPackagesToScan(new String[] {"com.jverstry"} );
        lcemfb.setPersistenceUnitName("MyPU");

        HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
        lcemfb.setJpaVendorAdapter(va);

        Properties ps = new Properties();
        ps.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
        ps.put("hibernate.hbm2ddl.auto", "create");
        lcemfb.setJpaProperties(ps);

        lcemfb.afterPropertiesSet();

        return lcemfb;

    }

    @Bean
    public DataSource dataSource(){

        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("org.hsqldb.jdbcDriver");
        ds.setUrl("jdbc:hsqldb:mem:testdb");
        ds.setUsername("sa");
        ds.setPassword("");

        return ds;

    }

    @Bean
    public PlatformTransactionManager transactionManager() {

        JpaTransactionManager tm = new JpaTransactionManager();

        tm.setEntityManagerFactory(
            this.entityManagerFactoryBean().getObject() );

        return tm;

    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

}

Data Item, Controller & Repository

The persisted data relies on Pojomatic:
@Entity
@AutoProperty
public class Item implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long ID;

    private String name = "";

    // Setter, Getters, Pojomatic methods...


}
The controller calls the injected repository class for a CRUD roundtrip, and retrieves the generated messages in the model:
@Controller
public class MyController {

    @Autowired
    private MyRepository rep;

    @RequestMapping(value = "/")
    public String home(Model model) {
        return "index";
    }

    @RequestMapping(value = "/roundtrip")
    public String Roundtrip(Model model) {

        model.addAttribute("Messages", rep.performRoundtrip());

        return "roundtrip";

    }

}
The repository annotated class, performs a CRUD (Create, Read, Update, Delete):
@Repository
public class MyRepository {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public List<String> performRoundtrip() {

        List<String> l = new ArrayList<String>();

        try {

            l.add("Before create");
            create(l);

            l.add("Before read I");
            read(l);

            l.add("Before update");
            update(l);

            l.add("Before read II");
            read(l);

            l.add("Before delete");
            delete(l);

            l.add("Before read III");
            read(l);

        } catch (Exception ex) {

            l.add(ex.toString());

        }

        return l;

    }

    private Item i = null;

    @Transactional
    public void create(List<String> l) {
        i = new Item();
        i.setName("Item A");
        l.add("- Before saving   : " + i);
        em.persist(i);
        l.add("- After saving    : " + i);
    }

    @Transactional
    public void read(List<String> l) {
        Item retr = em.find(Item.class, this.i.getID());
        l.add("- Retrieved       : " + retr);
    }

    @Transactional
    public void update(List<String> l) {
        i.setName("Item B");
        l.add("- Updated         : " + i);
        em.persist(i);
    }

    @Transactional
    public void delete(List<String> l) {
        l.add("- Deleting        : " + i);
        em.remove(i);
    }

}

JSP Page

The following roundtrip.jsp displays the messages collected during the roundtrip:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Roundtrip !!!</title>
    </head>
    <body>
        <c:forEach items="${Messages}" var="element">
            ${element}<br />
        </c:forEach><br />
        <a href="<c:url value='/'/>" />Home</a>
    </body>
</html>

Running the example

Once compiled, the example can be run with mvn tomcat:run. Then, browse http://localhost:8585/spring-web-jpa-roundtrip/.

The generated output is:
Before create
 - Before saving : Item{ID: {0}, name: {Item A}}
 - After saving : Item{ID: {1}, name: {Item A}}
Before read I
 - Retrieved : Item{ID: {1}, name: {Item A}}
Before update
 - Updated : Item{ID: {1}, name: {Item B}}
Before read II
 - Retrieved : Item{ID: {1}, name: {Item B}}
Before delete
 - Deleting : Item{ID: {1}, name: {Item B}}
Before read III
 - Retrieved : null

More Spring related posts here.

Sunday, 26 August 2012

Retrieving Hibernate Session from JPA Application

The equivalent of JPA's EntityManager in Hibernate is a Session. The following describes how to retrieve an Hibernate Session (and SessionFactory) from a JPA configured application:
public class RetrievingHibernateSessionExample {

    private static EntityManagerFactory EMF;
    private static EntityManager EM;

    public static void main(String[] args) {

        // Creating resources
        EMF = Persistence.createEntityManagerFactory("Standalone");
        EM = EMF.createEntityManager();

        Object o = EM.getDelegate();
        System.out.println(o.getClass());

        Session s = (Session) o;

        SessionFactory sf = s.getSessionFactory();

}
This solution was suggested by Lando on Stackoverflow.com, with a link to an informative post about co-existence between Hibernate, JPA, and EJB3.


Friday, 24 August 2012

JPA Tutorial with Examples using Hibernate in Standalone

This post is the starting point of a JPA introduction tutorial based on operational examples. It relies on a standalone usage of Hibernate. All code examples are available from Github in the JPA directory. Some error messages will be displayed when running some examples because of a known and harmless issue.

The following posts can be read individually or as a sequence:

Basics

Inheritance

Relationships

Criteria API



REM: This introduction tutorial does not cover for all features of the persistence package, but is enough to get started and write applications. More posts may be added in the future.

Thursday, 23 August 2012

JPA Many-To-Many Relationships

This post illustrates many-to-many relationships between two classes. Don't forget to set the ownership on one side.
@Entity
@AutoProperty
public class ManyToManyA implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @Property(policy=PojomaticPolicy.NONE) 
    @ManyToMany(cascade=CascadeType.ALL)
    private Collection<ManyToManyB> listOfB
        = new ArrayList<ManyToManyB>();

    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}


@Entity
@AutoProperty
public class ManyToManyB implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @Property(policy=PojomaticPolicy.NONE) 
    @ManyToMany(cascade=CascadeType.ALL, mappedBy="listOfB")
    private Collection<ManyToManyA> listOfA
        = new ArrayList<ManyToManyA>();
 
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}
The following:
ManyToManyA a1 = new ManyToManyA("AA1");
ManyToManyA a2 = new ManyToManyA("AA2");
ManyToManyA a3 = new ManyToManyA("AA3");
  
ManyToManyB b1 = new ManyToManyB("BB1");
ManyToManyB b2 = new ManyToManyB("BB2");

a1.getListOfB().add(b1);
b1.getListOfA().add(a1);
  
a3.getListOfB().add(b1);
b1.getListOfA().add(a3);
  
a2.getListOfB().add(b2);
b2.getListOfA().add(a2);
  
a3.getListOfB().add(b2);
b2.getListOfA().add(a3);
  
JPA.INSTANCE.save(a1);
JPA.INSTANCE.save(a2);
JPA.INSTANCE.save(a3);
JPA.INSTANCE.clear();
  
System.out.println("Retriving ManyToMany A's and their B's");

ManyToManyA retrA1
    = JPA.INSTANCE.get(ManyToManyA.class, a1.getId());
  
System.out.println(retrA1);
for (ManyToManyB origB : retrA1.getListOfB()) {
    ManyToManyB retrB
        = JPA.INSTANCE.get(
            ManyToManyB.class, origB.getId());
    System.out.println(retrB);
} System.out.println(" ");
  
ManyToManyA retrA2
    = JPA.INSTANCE.get(ManyToManyA.class, a2.getId());
  
System.out.println(retrA2);
for (ManyToManyB origB : retrA2.getListOfB()) {
    ManyToManyB retrB
        = JPA.INSTANCE.get(
            ManyToManyB.class, origB.getId());
    System.out.println(retrB);
} System.out.println(" ");
  
ManyToManyA retrA3
    = JPA.INSTANCE.get(ManyToManyA.class, a3.getId());
  
System.out.println(retrA3);
for (ManyToManyB origB : retrA3.getListOfB()) {
    ManyToManyB retrB
        = JPA.INSTANCE.get(
            ManyToManyB.class, origB.getId());
    System.out.println(retrB);
} System.out.println(" ");
  
System.out.println("Retriving ManyToMany B's and their A's");
  
ManyToManyB retrB1
= JPA.INSTANCE.get(ManyToManyB.class, b1.getId());
  
System.out.println(retrB1);
for (ManyToManyA origA : retrB1.getListOfA()) {
    ManyToManyA retrA
        = JPA.INSTANCE.get(
            ManyToManyA.class, origA.getId());
    System.out.println(retrA);
} System.out.println(" ");
  
ManyToManyB retrB2
= JPA.INSTANCE.get(ManyToManyB.class, b2.getId());
  
System.out.println(retrB2);
for (ManyToManyA origA : retrB2.getListOfA()) {
    ManyToManyA retrA
        = JPA.INSTANCE.get(
            ManyToManyA.class, origA.getId());
    System.out.println(retrA);
} System.out.println(" ");
Generates:
Retriving ManyToMany A's and their B's
ManyToManyA{id: {1}, s: {AA1}}
ManyToManyB{id: {1}, s: {BB1}}
 
ManyToManyA{id: {3}, s: {AA2}}
ManyToManyB{id: {2}, s: {BB2}}
 
ManyToManyA{id: {2}, s: {AA3}}
ManyToManyB{id: {1}, s: {BB1}}
ManyToManyB{id: {2}, s: {BB2}}
 
Retriving ManyToMany B's and their A's
ManyToManyB{id: {1}, s: {BB1}}
ManyToManyA{id: {1}, s: {AA1}}
ManyToManyA{id: {2}, s: {AA3}}
 
ManyToManyB{id: {2}, s: {BB2}}
ManyToManyA{id: {2}, s: {AA3}}
ManyToManyA{id: {3}, s: {AA2}}
The above examples are available from Github in the JPA directory. They rely on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

JPA Many-To-One Relationships (Unidirectional and Bidirectional)

This post illustrates simple many-to-one relationships between two classes.

Unidirectional

@Entity
@AutoProperty
public class ManyToOneUnidirectionalA implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @ManyToOne
    private ManyToOneUnidirectionalB b;
 
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}


@Entity
@AutoProperty
public class ManyToOneUnidirectionalB implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}
The following:
ManyToOneUnidirectionalA a1 = new ManyToOneUnidirectionalA("AA1");
ManyToOneUnidirectionalA a2 = new ManyToOneUnidirectionalA("AA2");
  
ManyToOneUnidirectionalB b = new ManyToOneUnidirectionalB("BBB");
  
a1.setB(b);
a2.setB(b);
  
JPA.INSTANCE.save(b);
JPA.INSTANCE.save(a1);
JPA.INSTANCE.save(a2);
JPA.INSTANCE.clear();
  
ManyToOneUnidirectionalA retrA1
    = JPA.INSTANCE.get(ManyToOneUnidirectionalA.class, a1.getId());
  
System.out.println("Retrieving ManyToOne Unidirectional A's");
System.out.println(retrA1);
  
ManyToOneUnidirectionalA retrA2
    = JPA.INSTANCE.get(ManyToOneUnidirectionalA.class, a2.getId());
  
System.out.println(retrA2);

System.out.println("Retrieving ManyToOne Unidirectional B");
ManyToOneUnidirectionalB retrB
    = JPA.INSTANCE.get(ManyToOneUnidirectionalB.class, b.getId());
  
System.out.println(retrB);
Generates:
Retrieving ManyToOne Unidirectional A's
ManyToOneUnidirectionalA{id: {1}, b: {ManyToOneUnidirectionalB{id: {1}, s: {BBB}}}, s: {AA1}}
ManyToOneUnidirectionalA{id: {2}, b: {ManyToOneUnidirectionalB{id: {1}, s: {BBB}}}, s: {AA2}}
Retrieving ManyToOne Unidirectional B
ManyToOneUnidirectionalB{id: {1}, s: {BBB}}

Bidirectional

A owns the relationship. We need to avoid Pojomatic circular reference issues too:
@Entity
@AutoProperty
public class ManyToOneBidirectionalA implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @Property(policy=PojomaticPolicy.NONE) 
    @ManyToOne
    private ManyToOneBidirectionalB b;
 
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}


@Entity
@AutoProperty
public class ManyToOneBidirectionalB implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @Property(policy=PojomaticPolicy.NONE) 
    @OneToMany(cascade=CascadeType.ALL, mappedBy="b")
    private Collection<ManyToOneBidirectionalA> a;
   
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}
The following:
ManyToOneBidirectionalA a11 = new ManyToOneBidirectionalA("BiAAA");
ManyToOneBidirectionalA a22 = new ManyToOneBidirectionalA("BiAAA");
ManyToOneBidirectionalB b2 = new ManyToOneBidirectionalB("BiBBB");
  
Collection<ManyToOneBidirectionalA> c
    = new ArrayList<ManyToOneBidirectionalA>();
c.add(a11);
c.add(a22);
b2.setA(c);
  
a11.setB(b2);
a22.setB(b2);
  
JPA.INSTANCE.save(b2);
JPA.INSTANCE.clear();

ManyToOneBidirectionalB retrB
    = JPA.INSTANCE.get(ManyToOneBidirectionalB.class, b2.getId());
  
System.out.println("Retrieving ManyToOne Bidirectional B");
System.out.println(retrB);
  
for (ManyToOneBidirectionalA orig : b2.getA()) {
    ManyToOneBidirectionalA retrA
        = JPA.INSTANCE.get(
     ManyToOneBidirectionalA.class, orig.getId());
    System.out.println(retrA);
}  
  
System.out.println("Retrieving ManyToOne Bidirectional A's");
  
ManyToOneBidirectionalA retrA11
    = JPA.INSTANCE.get(ManyToOneBidirectionalA.class, a11.getId());
  
System.out.println(retrA11);
System.out.println(retrA11.getB());
  
ManyToOneBidirectionalA retrA22
    = JPA.INSTANCE.get(ManyToOneBidirectionalA.class, a22.getId());
  
System.out.println(retrA22);
System.out.println(retrA22.getB());
Generates:
Retrieving ManyToOne Bidirectional B
ManyToOneBidirectionalB{id: {1}, s: {BiBBB}}
ManyToOneBidirectionalA{id: {1}, s: {BiAAA}}
ManyToOneBidirectionalA{id: {2}, s: {BiAAA}}
Retrieving ManyToOne Bidirectional A's
ManyToOneBidirectionalA{id: {1}, s: {BiAAA}}
ManyToOneBidirectionalB{id: {1}, s: {BiBBB}}
ManyToOneBidirectionalA{id: {2}, s: {BiAAA}}
ManyToOneBidirectionalB{id: {1}, s: {BiBBB}}
The above examples are available from Github in the JPA directory. They rely on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

JPA One-To-Many Relationships (Unidirectional and Bidirectional)

This post illustrates simple one-to-many relationships between two classes.

Unidirectional

We set the cascade type (i.e., propagation of operations) to ALL:
@Entity
@AutoProperty
public class OneToManyUnidirectionalA implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @OneToMany(cascade=CascadeType.ALL)
    private Collection<onetomanyunidirectionalb> b;
 
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}


@Entity
@AutoProperty
public class OneToManyUnidirectionalB implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}
The following:
OneToManyUnidirectionalA a = new OneToManyUnidirectionalA("AAA");
  
Collection<OneToManyUnidirectionalB> setB
    = new ArrayList<OneToManyUnidirectionalB>();
  
setB.add(new OneToManyUnidirectionalB("BBB"));
setB.add(new OneToManyUnidirectionalB("CCC"));

a.setB(setB);
  
JPA.INSTANCE.save(a);
JPA.INSTANCE.clear();
  
OneToManyUnidirectionalA retrA
    = JPA.INSTANCE.get(OneToManyUnidirectionalA.class, a.getId());
  
System.out.println("Retriving OneToMany Unidirectional A");
System.out.println(retrA);
  
System.out.println("Retriving OneToMany Unidirectional B's");
for (OneToManyUnidirectionalB origB : a.getB()) {
    OneToManyUnidirectionalB retrB
        = JPA.INSTANCE.get(
            OneToManyUnidirectionalB.class, origB.getId());
    System.out.println(retrB);
}
Generates:
Retriving OneToMany Unidirectional A
OneToManyUnidirectionalA{id: {1}, b: {[OneToManyUnidirectionalB{id: {1}, s: {BBB}}, OneToManyUnidirectionalB{id: {2}, s: {CCC}}]}, s: {AAA}}
Retriving OneToMany Unidirectional B's
OneToManyUnidirectionalB{id: {1}, s: {BBB}}
OneToManyUnidirectionalB{id: {2}, s: {CCC}}

Bidirectional

A owns the relationship:
@Entity
@AutoProperty
public class OneToManyBidirectionalA implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @OneToMany(cascade=CascadeType.ALL, mappedBy="a")
    private Collection<OneToManyBidirectionalB> b; 
 
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}


@Entity
@AutoProperty
public class OneToManyBidirectionalB implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    @Property(policy=PojomaticPolicy.NONE) 
    @ManyToOne
    private OneToManyBidirectionalA a;

    // Setters, Getters, Constructors, Pojomatic...

}
The following:
OneToManyBidirectionalB b2 = new OneToManyBidirectionalB("BiBBB");
OneToManyBidirectionalB c2 = new OneToManyBidirectionalB("BiCCC");
  
Collection<OneToManyBidirectionalB> setB2
    = new ArrayList<OneToManyBidirectionalB>();
  
setB2.add(b2);
setB2.add(c2);

a2.setB(setB2);
b2.setA(a2);
c2.setA(a2);
  
JPA.INSTANCE.save(a2);
JPA.INSTANCE.clear();
  
OneToManyBidirectionalA retrA2
    = JPA.INSTANCE.get(OneToManyBidirectionalA.class, a2.getId());
  
System.out.println("Retriving OneToMany Bidirectional A");
System.out.println(retrA2);

System.out.println("Retriving OneToMany Bidirectional B's");
    for (OneToManyBidirectionalB origB : a2.getB()) {
        OneToManyBidirectionalB retrB
     = JPA.INSTANCE.get(
         OneToManyBidirectionalB.class, origB.getId());
        System.out.println(retrB);
}
Generates:
Retriving OneToMany Bidirectional A
OneToManyBidirectionalA{id: {1}, b: {[OneToManyBidirectionalB{id: {1}, s: {BiBBB}}, OneToManyBidirectionalB{id: {2}, s: {BiCCC}}]}, s: {BiAAA}}
Retriving OneToMany Bidirectional B's
OneToManyBidirectionalB{id: {1}, s: {BiBBB}}
OneToManyBidirectionalB{id: {2}, s: {BiCCC}}
The above examples are available from Github in the JPA directory. They rely on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

Wednesday, 22 August 2012

JPA One-To-One Relationships (Unidirectional and Bidirectional)

This post illustrates simple one-to-one relationships between two classes.

Unidirectional

@Entity
@AutoProperty
public class OneToOneUnidirectionalA implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    @OneToOne
    private OneToOneUnidirectionalB b;

    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}


@Entity
@AutoProperty
public class OneToOneUnidirectionalB implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    // No reference to OneToOneUnidirectionalA
    // since this is a unidirectional relationship

    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}
The following:
OneToOneUnidirectionalA a = new OneToOneUnidirectionalA("AAA");
OneToOneUnidirectionalB b = new OneToOneUnidirectionalB("BBB");
  
a.setB(b);
  
JPA.INSTANCE.save(b);
JPA.INSTANCE.save(a);
JPA.INSTANCE.clear();
  
OneToOneUnidirectionalA retrA
    = JPA.INSTANCE.get(OneToOneUnidirectionalA.class, a.getId());
  
System.out.println("Retrieved OneToOne Unidirectional A:");
System.out.println(retrA);
System.out.println(retrA.getB());
  
OneToOneUnidirectionalB retrB
    = JPA.INSTANCE.get(OneToOneUnidirectionalB.class, b.getId());
  
System.out.println("Retrieved OneToOne Unidirectional B:");
System.out.println(retrB);
Generates:
Retrieved OneToOne Unidirectional A:
OneToOneUnidirectionalA{id: {1}, b: {OneToOneUnidirectionalB{id: {1}, s: {BBB}}}, s: {AAA}}
OneToOneUnidirectionalB{id: {1}, s: {BBB}}
Retrieved OneToOne Unidirectional B:
OneToOneUnidirectionalB{id: {1}, s: {BBB}}

Bidirectional

A owns the relationship. We need to avoid Pojomatic circular reference issues too:
@Entity
@AutoProperty
public class OneToOneBidirectionalA implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    @Property(policy=PojomaticPolicy.NONE)
    @OneToOne
    private OneToOneBidirectionalB b;

    // Setters, Getters, Constructors, Pojomatic...

}


@Entity
@AutoProperty
public class OneToOneBidirectionalB implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    @Property(policy=PojomaticPolicy.NONE)
    @OneToOne(mappedBy="b")
    private OneToOneBidirectionalA a;

    // Setters, Getters, Constructors, Pojomatic...

}
The following:
OneToOneBidirectionalA a2 = new OneToOneBidirectionalA("BiAAA");
OneToOneBidirectionalB b2 = new OneToOneBidirectionalB("BiBBB");
  
JPA.INSTANCE.save(b2);
JPA.INSTANCE.save(a2);
  
a2.setB(b2);
b2.setA(a2);
  
JPA.INSTANCE.update(b2);
JPA.INSTANCE.update(a2);
JPA.INSTANCE.clear();
  
OneToOneBidirectionalA retrA2
    = JPA.INSTANCE.get(OneToOneBidirectionalA.class, a2.getId());
  
System.out.println("Retrieved OneToOne Bidirectional A:");
System.out.println(retrA2 + " -> " + retrA2.getB());
  
OneToOneBidirectionalB retrB2
    = JPA.INSTANCE.get(OneToOneBidirectionalB.class, b2.getId());
  
System.out.println("Retrieved OneToOne Bidirectional B:");
System.out.println(retrB2 + " -> " + retrB2.getA());
Generates:
Retrieved OneToOne Bidirectional A:
OneToOneBidirectionalA{id: {1}, s: {BiAAA}} -> OneToOneBidirectionalB{id: {1}, s: {BiBBB}}
Retrieved OneToOne Bidirectional B:
OneToOneBidirectionalB{id: {1}, s: {BiBBB}} -> OneToOneBidirectionalA{id: {1}, s: {BiAAA}}
The above examples are available from Github in the JPA directory. They rely on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

JPA Inheritance Types - Joined, Single Table, Table Per Class

There are three strategies to store data of classes inheriting from each other in JPA. This is defined in the root classes of inheritance structures with the @Inheritance annotation.

Joined

The joined strategy creates a table for the root class of an inheritance structure, and a separate table for each inheriting class in the structure. The data of the root class table is not copied in the inheriting class tables.

This is a root class example:
@Entity
@AutoProperty
@Inheritance(strategy=InheritanceType.JOINED)
public class Joined implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    private String s;

    // Setter, Getters, Constructors, Pojomatic...

}

Single Table

The single table strategy creates a unique table for a given inheritance structure where all classes in the hierarchy are saved. This table contains a discriminating column which will help differentiate between the different classes. Each class must define a discriminating value with @DiscriminatorValue.

For the root class:
@Entity
@AutoProperty
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="discr", discriminatorType=DiscriminatorType.INTEGER)
@DiscriminatorValue("44")
public class SingleTable implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    private String s;

    // Setter, Getters, Constructors, Pojomatic...

}
For an inheriting class:
@Entity
@AutoProperty
@DiscriminatorValue("45")
public class InheritsSingleTable extends SingleTable {

    ...

}

Table Per Class

The table per class strategy create a separate table per class.

Root class example:
@Entity
@AutoProperty
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class TablePerClass implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private long id;
 
    private String s;

    // Setter, Getters, Constructors, Pojomatic...

}
Notice that one must use a TABLE generation type for the Id.

Check

The following:
JPA.INSTANCE.clear();

InheritsJoined ij = new InheritsJoined();
ij.setS("IJ1");
ij.setS2("IJ2");

JPA.INSTANCE.save(ij);

InheritsSingleTable st
    = new InheritsSingleTable();
st.setS("ST1");
st.setS2("ST2");

JPA.INSTANCE.save(st);

InheritsTablePerClass tpc
    = new InheritsTablePerClass();
tpc.setS("TPC1");
tpc.setS2("TPC2");

JPA.INSTANCE.save(tpc);

JPA.INSTANCE.clear();

InheritsJoined retr_ij = JPA.INSTANCE.get(
    InheritsJoined.class, ij.getId());
System.out.println("Source == Retrieved: " + (ij==retr_ij));
System.out.println(retr_ij);

InheritsSingleTable retr_st = JPA.INSTANCE.get(
    InheritsSingleTable.class, st.getId());
System.out.println("Source == Retrieved: " + (st==retr_st));
System.out.println(retr_st);

InheritsTablePerClass retr_tpc = JPA.INSTANCE.get(
    InheritsTablePerClass.class, tpc.getId());
System.out.println("Source == Retrieved: " + (tpc==retr_tpc));
System.out.println(retr_tpc);
Generates the following output:
Source == Retrieved: false
InheritsJoined{id: {1}, s: {IJ1}, s2: {IJ2}}
Source == Retrieved: false
InheritsSingleTable{id: {1}, s: {ST1}, s2: {ST2}}
Source == Retrieved: false
InheritsTablePerClass{id: {1}, s: {TPC1}, s2: {TPC2}}
The above example is available from Github in the JPA directory. It relies on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

JPA Inheritance - Non Entity Super Class

An entity can inherit of a non-entity super class. The consequence is that the non-entity class data is not persisted.

For example:
@AutoProperty
public class NonEntitySuperClass {

 private String s;

    // Setter, Getters, Constructors, Pojomatic...

}
A class extends this non-entity class:
@Entity
@AutoProperty
public class InheritingNonEntitySuperClass
    extends NonEntitySuperClass
        implements Serializable {
 
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    private String s2;

    // Setter, Getters, Constructors...

}
The following code:
JPA.INSTANCE.clear();

InheritingNonEntitySuperClass insc
    = new InheritingNonEntitySuperClass();
insc.setS("P1P");
insc.setS2("AZ3");
  
JPA.INSTANCE.save(insc);
JPA.INSTANCE.clear();
  
InheritingNonEntitySuperClass retr = JPA.INSTANCE.get(
    InheritingNonEntitySuperClass.class, insc.getId());

System.out.println("Source == Retrieved: " + (insc==retr));
System.out.println(retr);
Generates the following output:
Source == Retrieved: false
InheritingNonEntitySuperClass{s: {null}, id: {1}, s2: {AZ3}}
Notice that the s value is null, instead of P1P.

The above example is available from Github in the JPA directory. It relies on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

JPA Inheritance - Mapped Super Class

Mapped super classes are just like entities, but cannot be used like entities. They have ids and data to persist, but there is no corresponding table in the database. 

For example:
@MappedSuperclass
@AutoProperty
public class MappedSuperClass implements Serializable {

 @Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 private long id; 
 
 private String s;

    // Setter, Getters, Constructors, Pojomatic...

}
A class extends the mapped super class:
@Entity
@AutoProperty
public class InheritingMappedSuperClass extends MappedSuperClass {

 private String s2;

    // Setter, Getters, Constructors...

}
The following code:
JPA.INSTANCE.clear();

InheritingMappedSuperClass ce = new InheritingMappedSuperClass();
ce.setS("QQQ");
ce.setS2("DDD");

JPA.INSTANCE.save(ce);
JPA.INSTANCE.clear();
  
InheritingMappedSuperClass retr = JPA.INSTANCE.get(
    InheritingMappedSuperClass.class, ce.getId());

System.out.println("Source == Retrieved: " + (ce==retr));
System.out.println(retr);
Generates the following output:
Source == Retrieved: false
InheritingMappedSuperClass{id: {1}, s: {QQQ}, s2: {DDD}}
The above example is available from Github in the JPA directory. It relies on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

JPA Inheritance - Abstract Entity

An abstract class can be made a JPA entity. The only difference is that such classes cannot be instantiated.

For example:
@Entity
@AutoProperty
public abstract class AbstractEntity implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    private String s;

    // Setter, Getters, Constructors, Pojomatic...

}
A class extends the abstract class:
@Entity
@AutoProperty
public class ConcreteEntity extends AbstractEntity {

    private String s2;

    // Setter, Getters, Constructors...

}
The following code:
JPA.INSTANCE.clear();

ConcreteEntity ce = new ConcreteEntity();
ce.setS("AAA");
ce.setS2("BBB");

JPA.INSTANCE.save(ce);
JPA.INSTANCE.clear();

ConcreteEntity retr = JPA.INSTANCE.get(
    ConcreteEntity.class, ce.getId());

System.out.println("Source == Retrieved: " + (ce==retr));
System.out.println(retr);
Generates the following output:
Source == Retrieved: false
ConcreteEntity{id: {1}, s: {AAA}, s2: {BBB}}
The above example is available from Github in the JPA directory. It relies on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

JPA @ElementCollection for Embeddables

The @ElementCollection entity is a mean to create one-to-many relationships between entities and embeddables, using Collection, List, Set and Map. This annotation must also be used for basic types.

For example:
@AutoProperty
@Entity
public class ReferringItem implements Serializable {

    @Id
    private long id;

    // Element collection is required for basic types
    // and embeddables. Such elements are stored in
    // a separate table.
    @ElementCollection
    private Collection<AnEmbeddable> myCollection
        = new ArrayList<AnEmbeddable>();

    // By default, data is fetched lazily (when
    // used for the first time). Making it eager
    // loads the data as soon as possible.
    @ElementCollection(fetch=FetchType.EAGER)
    private Set<Long> mySet = new HashSet<Long>();

    // When not using generics, one must specify
    // the collection type (i.e., target class)
    @ElementCollection(targetClass=String.class)
    private List myList = new ArrayList();

    // Element collection is required when the map
    // value is a basic type or an embeddable
    @ElementCollection
    private Map<String,AnEmbeddable> map
        = new HashMap<String,AnEmbeddable>();

    // Setter & Getter, Constructor... 

}
The following:
@AutoProperty
JPA.INSTANCE.clear();

ReferringItem ri = new ReferringItem();

ArrayList<AnEmbeddable> coll
    = new ArrayList<AnEmbeddable>();
coll.add(new AnEmbeddable("Coll1"));
coll.add(new AnEmbeddable("Coll2"));
ri.setMyCollection(coll);

Set<Long> set = new HashSet<Long>();
set.add(Long.MIN_VALUE);
set.add(33l);
ri.setMySet(set);

List list = new ArrayList();
list.add("aaa");
list.add("bbb");
ri.setMyList(list);

Map<String,AnEmbeddable> map
    = new HashMap<String,AnEmbeddable>();
map.put("prt", new AnEmbeddable("Map1"));
map.put("frd", new AnEmbeddable("Map2"));
ri.setMap(map);

JPA.INSTANCE.save(ri);
JPA.INSTANCE.clear();

ReferringItem retr = JPA.INSTANCE.get(
ReferringItem.class, ri.getId());
System.out.println("Source == Retrieved: " + (ri==retr));

System.out.println("Retrieved Collection:");
for (AnEmbeddable ae : retr.getMyCollection()) {
    System.out.println(ae);
}

System.out.println("Retrieved Set:");
for (Long l : retr.getMySet()) {
    System.out.println(l);
}

System.out.println("Retrieved List:");
for (Iterator it = retr.getMyList().iterator(); it.hasNext();) {
    System.out.println(it.next());
}

System.out.println("Retrieved Map:");
for (Map.Entry<String,AnEmbeddable> e : map.entrySet()) {
    System.out.println(e.getKey() + " - " + e.getValue());
}
Generates:
Source == Retrieved: false
Retrieved Collection:
AnEmbeddable{s: {Coll1}}
AnEmbeddable{s: {Coll2}}
Retrieved Set:
-9223372036854775808
33
Retrieved List:
aaa
bbb
Retrieved Map:
prt - AnEmbeddable{s: {Map1}}
frd - AnEmbeddable{s: {Map2}}
We make sure the retrieved object instance is not identical to the persisted source object. The retrieved object is retrieved from the database.

The above example is available from Github in the JPA directory. It relies on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.

Tuesday, 21 August 2012

Hibernate/JPA Create-Drop Known Issue

Often, running Hibernate/JPA in create drop mode:

  <property name="hibernate.hbm2ddl.auto" value="create-drop"/>

generates multiple errors like this:

  Unsuccessful: alter table XXX drop constraint YYY

Thanks to feedback from Mikko Maunu on StackOverflow, the following issue can be explained by the fact that Hibernate does not check whether an object exists when it deletes it. The underlying database often triggers an error.

Since the create-drop mode drops many objects, these errors happen frequently, but can be ignored.

Monday, 20 August 2012

JPA Primary Keys, Composite and Unique

This post illustrates JPA entity key, be them unique or composite. The code examples are available from Github in the JPA directory.

Unique Key

An entity can used a simple key made of a unique field. The only requirement is to annotate this field with @Key. The set of allowed types for unique keys is:

  boolean Boolean
  byte Byte
  char Character
  int Integer
  long Long
  short Short

  String
  BigInteger
  BigDecimal

  @Temporal(TemporalType.DATE)
  java.util.Date
  java.sql.Date
  java.math.BigDecimal
  java.math.BigInteger

  // Don't - Not recommended
  double Double
  float Float

Generated Value Strategy

The @GeneratedValue annotation can be used to specify an id generation strategy via a GenerationType. A sequence name can be specified using the proper annotation property.

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private long id; 

Composite Key

Here is an example of a composite key:
/**
 * Composite key must implement Serializable
 * and must be public.
 */
@AutoProperty
public class CompositeKey implements Serializable {

    // Must be public or protected
    public String s;
    public long l;

    // Default public parameter-less
    // constructor is required
    public CompositeKey() { }

    // equals() must be implemented
    @Override
    public boolean equals(Object o) {
        return Pojomatic.equals(this, o);
    }

    // hashCode() must be implemented
    @Override
    public int hashCode() {
        return Pojomatic.hashCode(this);
    }

    @Override
    public String toString() {
        return Pojomatic.toString(this);
    }

}
Using @EmbeddedId:
@Entity
public class WithEmbeddedId {

    @EmbeddedId
    private CompositeKey id;

    private String data;

    // Setter & Getter

}
The entity needs to declare the composite key with @EmbeddedId.

Using @IdClass:
@Entity
@IdClass(CompositeKey.class)
public class WithIdClass {

    @Id
    String s;

    @Id
    long l;

    private String someData;

    public WithIdClass() { }

    // Setter & Getter

}
With @IdClass, the class must declare the @Id fields matching the composite key fields.

JPA Lifecycle Annotations

This post illustrates how to use JPA's life cycle annotations. These can be used on method to perform actions before or after CRUD operations. The code example is available from Github in the JPA directory.

We define two classes, one with annotations WithLifeCycleAnnotations and one without annotations NoLifeCycleAnnotations. This example operates Hibernate JPA in a standalone in-memory mode.

With annotations:
@Entity
public class WithLifeCycleAnnotations {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long ID;

    private String name = "";

    @PostLoad
    public void postLoad() {
        System.out.println("Post Load called !!!");
    }

    @PostPersist
    public void postPersist() {
        System.out.println("Post Persist called !!!");
    }

    @PostRemove
    public void postRemove() {
        System.out.println("Post Remove called !!!");
    }

    @PostUpdate
    public void postUpdate() {
        System.out.println("Post Update called !!!");
    }

    @PrePersist
    public void prePersist() {
        System.out.println("Pre Persist called !!!");
    }

    @PreRemove
    public void preRemove() {
        System.out.println("Pre Remove called !!!");
    }

    @PreUpdate
    public void preUpdate() {
        System.out.println("Pre Update called !!!");
    }

    // Setters & Getters...

}
The following:
NoLifeCycleAnnotations nlca = new NoLifeCycleAnnotations();
nlca.setName("AAA");

System.out.println("Saving NO lifecycle annotations");
JPA.INSTANCE.save(nlca);

System.out.println("Reading NO lifecycle annotations");
NoLifeCycleAnnotations nlcaRetr =
    JPA.INSTANCE.get(NoLifeCycleAnnotations.class, nlca.getID());

System.out.println("Updating NO lifecycle annotations");
nlca.setName("BBB");
JPA.INSTANCE.update(nlca);

System.out.println("Deleting NO lifecycle annotations");
nlca.setName("BBB");
JPA.INSTANCE.delete(nlca);


WithLifeCycleAnnotations wlca = new WithLifeCycleAnnotations();
wlca.setName("AAA");

System.out.println("Saving WITH lifecycle annotations:");
JPA.INSTANCE.save(wlca);

System.out.println("Reading WITH lifecycle annotations:");
WithLifeCycleAnnotations wlcaRetr =
    JPA.INSTANCE.get(WithLifeCycleAnnotations.class, wlca.getID());

System.out.println("Updating WITH lifecycle annotations:");
wlca.setName("BBB");
JPA.INSTANCE.update(wlca);

System.out.println("Deleting WITH lifecycle annotations:");
wlca.setName("BBB");
JPA.INSTANCE.delete(wlca);
Generates the following output:
Saving NO lifecycle annotations
Reading NO lifecycle annotations
Updating NO lifecycle annotations
Deleting NO lifecycle annotations

Saving WITH lifecycle annotations:
Pre Persist called !!!
Post Persist called !!!
Reading WITH lifecycle annotations:
Updating WITH lifecycle annotations:
Pre Update called !!!
Post Update called !!!
Deleting WITH lifecycle annotations:
Pre Remove called !!!
Post Remove called !!
For some reason, @PostLoad is not invoked when using JPA/Hibernate in standalone mode.

Sunday, 19 August 2012

JPA Transaction Types and JTA

In the persistence.xml JPA configuration file, one has to specify the transaction type for each persistence unit:
<persistence ... >
    <persistence-unit name="..." transaction-type="RESOURCE_LOCAL">
        ...
    </persistence-unit>
    ...
</persistence>
There are two possible values: RESOURCE_LOCAL and JTA.

Resource Local

  • This is the typical value for a standalone application
  • One is responsible for the creation of the EntityManager via the EntityManagerFactory
  • Transactions are of type EntityTransaction
  • One must use begin() and commit() around every transaction
  • If multiple instances of EntityManager are created for the same persistence unit, multiple persistence contexts are created too. Meaning, transactions are NOT synchronized across these in the application. A solution is to use UserTransaction. Another is to avoid using multiple EntityManager for the same persistence unit.
Usage:
// Creating resources
EntityManagerFactory EMF
    = Persistence.createEntityManagerFactory("Standalone");
EntityManager EM = EMF.createEntityManager();

// Transaction
EntityTransaction et = EM.getTransaction();

try { 
    et.begin();
    // Operations...
    et.commit();
} catch(Exception ex) {
    et.rollback();
}

// Closing resources
EM.close();
EMF.close();

JTA

JTA stands for Java Transaction API. It is part of the Java EE specification. 
  • This is the typical value for a container application
  • The EntityManager is provided by the container (unique instance across the application)
  • Transactions can be declared with @TransactionAttribute and will be managed automatically
  • All transactions are synchronized over the application with a unique JTA transaction
Usage:
@PersistenceContext(unitName="Container")
private EntityManager EM;

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void myMethod() throws Exception {

    Item i = EM.find(Item.class, 997);

    // ...

}

More about JPA/JTA transactions here, more about transaction subtleties here.

Saturday, 18 August 2012

Standalone Hibernate JPA In-Memory Example

This post describes an hibernate/JPA example in a standalone application (no application server or container required). It is available from Github, in the Standalone-Hibernate-JPA directory.

The purpose is to activate Hibernate with an in-memory database instance and illustrate basic CRUD (Create, Read, Update, Delete) operations. We use a simple JPA annotated item and Pojomatic for a nice string representation:
@Entity
@AutoProperty
public class Item implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long ID;

    // Setter & Getters, Pojomatic methods...

}
The CRUD operations are:
public static void save(Object o) {
    EntityTransaction et = EM.getTransaction();
    et.begin();
    EM.persist(o);
    et.commit();
}

public static <T> T get(Class<T> entityType, Object key) {
    return EM.find(entityType, key);
}

public static void update(Object o) {
    EntityTransaction et = EM.getTransaction();
    et.begin();
    EM.merge(o);
    et.commit();
}

public static void delete(Object o) {
    EntityTransaction et = EM.getTransaction();
    et.begin();
    EM.remove(o);
    et.commit();
}
The following:
private static EntityManagerFactory EMF;
private static EntityManager EM;

public static void main(String[] args) {

    // Creating resources
    EMF = Persistence.createEntityManagerFactory("Standalone");
    EM = EMF.createEntityManager();

    // Create
    Item i = new Item();
    i.setName("Item A");
    System.out.println("Before saving   : " + i);
    save(i);
    System.out.println("After saving    : " + i);

    // Read
    Item retr = get(Item.class, i.getID());
    System.out.println("Retrieved I     : " + retr);

    // Update
    i.setName("Item B");
    System.out.println("Updated         : " + i);
    update(i);
    retr = get(Item.class, i.getID());
    System.out.println("Retrieved II    : " + retr);

    // Delete
    System.out.println("Deleting        : " + i);
    delete(i);
    retr = get(Item.class, i.getID());
    System.out.println("Retrieved III   : " + retr);

    // Closing resources
    EM.close();
    EMF.close();

}
Generates the following output:
Before saving   : Item{ID: {0}, name: {Item A}}
After saving    : Item{ID: {1}, name: {Item A}}
Retrieved I     : {1}, name: {Item A}}
Updated         : Item{ID: {1}, name: {Item B}}
Retrieved II    : Item{ID: {1}, name: {Item B}}
Deleting        : Item{ID: {1}, name: {Item B}}
Retrieved III   : null
Notice that the id value is set after saving.

REM: The way transactions are used in the above example is not clean. Typically, one should wrap them in a try catch as following to trigger rollbacks when necessary:
EntityTransaction et = EM.getTransaction();
try {
    et.begin();
    EM.merge(o); // Or any other operations...
    et.commit();
} catch(Exception ex) {
    et.rollback();
    throw ex;
}

The Web Application version of this example is available here. More about JPA transaction types and the Java Transaction API (JTA) here.

--------------------

The persistence.xml file is configured as following (with hsqldb):
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">

    <persistence-unit name="Standalone" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>com.jverstry.standalone.Item</class>
        <properties>
          <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
          <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:testdb"/>
          <property name="javax.persistence.jdbc.user" value="sa"/>
          <property name="javax.persistence.jdbc.password" value=""/>
          <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
          <property name="hibernate.hbm2ddl.auto" value="create"/>
        </properties>

    </persistence-unit>

</persistence>
The dependencies are:
<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.2.8</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>4.1.5.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.1.5.Final</version>
</dependency>
<dependency>
    <groupId>org.pojomatic</groupId>
    <artifactId>pojomatic</artifactId>
    <version>1.0</version>
<type>jar</type>
</dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.6</version>
</dependency>
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>6.0</version>
    <type>jar</type>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.0.0.GA</version>
    <scope>test</scope>
</dependency>