perbandingan berbagai provider jpa

Upload: lukman-farizi

Post on 04-Apr-2018

231 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/29/2019 Perbandingan berbagai Provider JPA

    1/58

    MASARYKOVA UNIVERZITA

    FAKULTA INFORMATIKY

    Comparison of JPA providersand issues with migration

    DIPLOMA THESIS

    Lukas Sembera

    Brno, June 2012

  • 7/29/2019 Perbandingan berbagai Provider JPA

    2/58

    Declaration

    Hereby I declare, that this paper is my original authorial work, whichI have worked out by my own. All sources, references and literatureused or excerpted during elaboration of this work are properly citedand listed in complete reference to the due source.

    Lukas Sembera

    Advisor: Jir Pechanec, Red Hat Czech, s.r.o.

    ii

  • 7/29/2019 Perbandingan berbagai Provider JPA

    3/58

    Acknowledgement

    I would like to thank my technical advisor Jir Pechanec from RedHat Czech for his valuable comments and suggestions. I would alsolike to thank my fiancee Daria for her support during writing.

    iii

  • 7/29/2019 Perbandingan berbagai Provider JPA

    4/58

    Abstract

    This thesis aims to compare three implementations of the JPA stan-dard specifically Hibernate, OpenJPA and EclipseLink. Except thecomparison, it will also describe the migration processes of variousreal-world applications between those JPA implementation and doc-ument the issues that the developers might typically run into.

    The practical part involves developing an application which wouldprovide a support when migrating projects between those three JPAproviders.

    iv

  • 7/29/2019 Perbandingan berbagai Provider JPA

    5/58

    Keywords

    JPA, JPA2, Hibernate, OpenJPA, EclipseLink, Java, persistence, rela-tional, databases, Scala

    v

  • 7/29/2019 Perbandingan berbagai Provider JPA

    6/58

    Contents

    1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.1 Database management systems . . . . . . . . . . . . . . 6

    1.1.1 Relational databases . . . . . . . . . . . . . . . . 71.1.2 Object-oriented databases . . . . . . . . . . . . . 71.1.3 NoSQL databases . . . . . . . . . . . . . . . . . . 8

    1.2 Object-relational mismatch . . . . . . . . . . . . . . . . . 81.3 Brief history of Java persistence solutions . . . . . . . . 9

    1.3.1 JDBC . . . . . . . . . . . . . . . . . . . . . . . . . 9

    1.3.2 EJB 2.x entity beans . . . . . . . . . . . . . . . . . 101.3.3 JDO . . . . . . . . . . . . . . . . . . . . . . . . . . 111.3.4 myBatis . . . . . . . . . . . . . . . . . . . . . . . 11

    1.4 JPA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.5 Goals of the thesis . . . . . . . . . . . . . . . . . . . . . . 12

    2 Comparison of JPA providers . . . . . . . . . . . . . . . . . . 132.1 Methodology of the comparison . . . . . . . . . . . . . 132.2 Identifier generation . . . . . . . . . . . . . . . . . . . . 142.3 Performance . . . . . . . . . . . . . . . . . . . . . . . . . 15

    2.3.1 Batch inserts . . . . . . . . . . . . . . . . . . . . . 182.3.2 Searching by ID . . . . . . . . . . . . . . . . . . . 182.3.3 Basic JPA QL test . . . . . . . . . . . . . . . . . . 192.3.4 Basic criteria API test . . . . . . . . . . . . . . . . 192.3.5 Aggregate function . . . . . . . . . . . . . . . . . 202.3.6 Performance summary . . . . . . . . . . . . . . . 20

    2.4 Type conversion . . . . . . . . . . . . . . . . . . . . . . . 212.5 Caching support. . . . . . . . . . . . . . . . . . . . . . . 222.6 Entity lifecycle and transactional events . . . . . . . . . 242.7 Schema generation . . . . . . . . . . . . . . . . . . . . . 252.8 Support for stored procedures . . . . . . . . . . . . . . . 272.9 Integrating with other frameworks . . . . . . . . . . . . 28

    2.10 Licenses . . . . . . . . . . . . . . . . . . . . . . . . . . . 292.11 Documentation quality . . . . . . . . . . . . . . . . . . . 302.12 Build systems . . . . . . . . . . . . . . . . . . . . . . . . 312.13 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

    3 Experimental migration of JPA applications . . . . . . . . . 333.1 Migrating from Hibernate . . . . . . . . . . . . . . . . . 33

    1

  • 7/29/2019 Perbandingan berbagai Provider JPA

    7/58

    3.2 Migrating from OpenJPA . . . . . . . . . . . . . . . . . . 35

    3.3 Migrating from EclipseLink . . . . . . . . . . . . . . . . 363.4 Migration summary. . . . . . . . . . . . . . . . . . . . . 38

    4 Automatic migration tool . . . . . . . . . . . . . . . . . . . . 394.1 The application architecture . . . . . . . . . . . . . . . . 394.2 Java source files parsing . . . . . . . . . . . . . . . . . . 414.3 Ideas for a further development . . . . . . . . . . . . . . 43

    5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45A Generated database schemas . . . . . . . . . . . . . . . . . . 46

    A.1 Hibernate. . . . . . . . . . . . . . . . . . . . . . . . . . . 46A.2 OpenJPA . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

    A.3 EclipseLink. . . . . . . . . . . . . . . . . . . . . . . . . . 50

    2

  • 7/29/2019 Perbandingan berbagai Provider JPA

    8/58

    Listings

    1.1 Sample of JDBC code . . . . . . . . . . . . . . . . . . . . 92.1 DDL defining sample database schema . . . . . . . . . 162.2 Sample stored procedure . . . . . . . . . . . . . . . . . . 274.1 Recursively searching the abstract syntax tree for vendor-

    specific annotations using Scala pattern matching . . . 42A.1 Hibernate-generated sample database schema . . . . . 46A.2 OpenJPA-generated sample database schema . . . . . . 48A.3 EclipseLink-generated sample database schema . . . . 50

    3

  • 7/29/2019 Perbandingan berbagai Provider JPA

    9/58

    List of Figures

    2.1 ER diagram of sample database schema 15

    4.1 Class diagram of the migration application 44

    4

  • 7/29/2019 Perbandingan berbagai Provider JPA

    10/58

    List of Tables

    2.1 Batch inserts on PostgreSQL test results 182.2 Batch inserts on MySQL test results 182.3 Find by ID test results 192.4 Fetch all users using JPA QL test results 192.5 Fetch all users using criteria API test results 192.6 Complex join using JPA QL test results 202.7 Complex join using criteria API test results 202.8 Feature matrix 31

    5

  • 7/29/2019 Perbandingan berbagai Provider JPA

    11/58

    1 Introduction

    Every application, except the most basic ones, has to deal with data.The very first computers were designed as black boxes receiving in-put, doing some calculations and producing output. Since then, com-puters have become much more complicated and nowadays they domuch more than such simple data processing. Nevertheless, they stilloperate with data stored on some kind of a permanent storage de-vice, such as hard drive.

    Input data for an application could be saved, without much think-ing, into an ordinary text file. However, such files are next to impos-sible to machine process because they do not follow any rules whichwould describe their structure. For this reason, variety of rules thedata have to follow are often introduced (e.g. the structure is de-scribed by XML with an appropriate XML Schema definition).

    Even if the data are in easily computer-readable form, the biggestproblem with this file-based approach remains. It is still just a textfile and, therefore, the data access is limited by I/O operations of theoperating system. Demands of current enterprise applications, how-ever, go far beyond the possibilities of such file-based persistence. Werequire reliability, transaction management, high-performance con-

    current access, advanced user access control and much more. To sup-port all of these advanced features, database management systemshave been invented.

    1.1 Database management systems

    A database management system (DBMS), as defined in [1], is a soft-ware designed to assist in maintaining and utilizing large collectionsof data. Each DBMS has its model, which describes data, data rela-tionships, semantics and consistency constraints[2]. It is basically atheoretical foundation, upon which database management systemsoperate.

    During last few decades, several database models have been in-vented. In 1960, IBM introduced their database management systemIMS, which internally uses hierarchical database model. Hierarchicalmodel stores data in records, which are connected with each other

    6

  • 7/29/2019 Perbandingan berbagai Provider JPA

    12/58

    1. INTRODUCTION

    through links, creating tree-like structures [2]. An evolution of the

    hierarchical model is the network model, which allows records to beconnected in arbitrary graphs and thus making data modelling modeflexible (e.g. allows many-to-many relationships between records).Even though hierarchical and network databases exist and are still inuse1, the models have many flaws (further discussed in [4]), whichmake their usage in certain scenarios particularly complicated.

    1.1.1 Relational databases

    In 1970, E. F. Codd published a revolutionary paper [5], where he

    laid out the concept of the relational data model, which is the theo-retical foundation of relational databases. For its flexibility2, simplic-ity and strong but simple formal background (which allows math-ematical reasoning about data) its popularity grew rapidly. A lot ofboth commercial and open-source implementations exist; they arevery mature and industry-proven, relational model itself is very wellunderstood and documented. For these reasons, relational databasesbasically mean an industry standard and their knowledge is essentialfor every programmer.

    1.1.2 Object-oriented databasesIn last decade, under the influence of object oriented programming,the concept of object oriented (OODBMS) and object-relational data-base management (ORDBMS) systems has aroused. OODBMS allowobject graphs to be stored to the database directly and are very of-ten integrated with the programming language itself. Thus, they pro-vide homogeneous environment and remove the necessity of varioustransformations when data are passed back and forth between ap-plication and data layer. Even though object oriented databases haveundeniable benefits and advantages, their popularity is not very high.

    1. Probably the best known hierarchical database is the Windows System Reg-istry [3]2. By flexibility I mean the ability of the relational model to hide its inter-nal data representation. Clients thus do not need any knowledge, how data arephysically stored and, therefore, are not affected when the server implementationchanges.

    7

  • 7/29/2019 Perbandingan berbagai Provider JPA

    13/58

    1. INTRODUCTION

    Not only because of those enormous amounts data that are already

    stored in relational databases (and migration of which would not becost free), but also because of some technical issues they are still fac-ing and which are still not yet resolved3. Moreover, vendors of rela-tional databases are integrating various object-oriented features intotheir products and thus are making the need for pure object-orienteddatabases less urgent.

    1.1.3 NoSQL databases

    Recently, with the rise of interest in cloud computing, a new cate-

    gory or databases has occurred, so called NoSQL4

    databases. NoSQLis neither a specific database model, nor an evolution of relational orobject oriented databases, but it is rather a group of database prod-ucts which are suited to specific scenarios, often where other solu-tions fail. They often offer only a feature subset of relational data-bases, but they are superior in certain characteristics. For exampleMongoDB is a document-oriented database, which shines at speedand scalability, but from design decision it lacks decent transactionmanagement5 and, therefore, its use case is in large clusters wheretransactional behaviour is not crucial.

    1.2 Object-relational mismatch

    Currently, most of the data are stored in relational databases. In pro-gramming languages, however, object-oriented approach predomi-nates. It best reflects the reality, models interactions of entities andtheir behaviour. In object-oriented programming, there are funda-mental concepts like association, inheritance or polymorphism, whichdo not have corresponding counterparts in the world of relationaldatabases.

    The object-relational mismatch occurs when data, representingsome business information we need to process, are stored in a re-lational database. In the application processing the data, however,

    3. More discussed at http://www.leavcom.com/db_08_00.htm4. Abbreviation of Not Only SQL5. MongoDB supports atomic operations on a single document

    8

    http://www.leavcom.com/db_08_00.htmhttp://www.leavcom.com/db_08_00.htm
  • 7/29/2019 Perbandingan berbagai Provider JPA

    14/58

    1. INTRODUCTION

    object-oriented approach is used and everything is modelled using

    objects and other OOP concepts. Therefore, transformations are neededeach time data are passed between the application layer and the datalayer. These transformations might not be complicated if the objectsare simple data holders containing only basic data types, but oncewe want to have a use of advanced OOP features, things would getmuch more complicated.

    1.3 Brief history of Java persistence solutions

    1.3.1 JDBC

    The object-relational mismatch can be tackled by hand using plainJDBC, which is Javas API for database access. The API is database-independent6 and database vendors provide JDBC drivers for theirsystems. Here is a very simple code which saves a person into a da-tabase using JDBC:

    public void savePerson(Person p) throws SQLException {

    String query = "INSERT INTO PERSON VALUES (DEFAULT,

    ?, ?)";

    PreparedStatement stmt =connection.prepareStatement(query);

    stmt.setString(1, p.getName());

    stmt.setString(2, p.getSurname());

    stmt.executeUpdate();

    }

    Listing 1.1: Sample of JDBC code

    The advantage of this approach is that it gives the programmerfull control over SQL queries sent to the database. On the other hand,

    one can observe that such code is rather low-level, and pollutes ourservice layer with SQL statements and checked exceptions. It alsoleads to procedural code because it forces a programmer to un-

    6. Even though the JDBC API is database-independent, the SQL statements arenot, so it is important to be careful when utilizing non-standard SQL queries.

    9

  • 7/29/2019 Perbandingan berbagai Provider JPA

    15/58

    1. INTRODUCTION

    pack primitive properties7 from domain objects and put them into

    SQL statements manually. This is especially tedious and error-pronewhen we work with larger object graphs and cascaded saving.

    So, for reasons above we usually search for a tool or a framework,which does the tedious work for us, analyses our classes, generatesSQL statements, automatically bounds parameters, etc. In comingparagraphs, Ill briefly discuss different approaches to the Java object-relational mapping.

    It is important to remember, however, that Java database pro-grammers can never avoid JDBC entirely. Since all persistence so-lutions are built on top of JDBC, its understanding is essential to

    fine-tune the persistence framework in certain scenarios or to checklogs in case that something goes wrong. As Gavin King and Chris-tian Bauer in their book state, high-level persistence solutions are nothere for programmers who do not want to learn or do not understandJDBC, SQL or the relational model itself. They are here for those, whohave already done it the hard way ([6]).

    1.3.2 EJB 2.x entity beans

    Since the very beginning of the J2EE specification there has beena technology aiming Java persistence, called EJB entity beans. En-tity beans are container managed components providing various ser-vices, such as persistence or transaction management. The specifica-tion, however, was largely over-engineered from the beginning[7]. Itbuilds on the fundamental concept that persistence should be non-intrusive to the application and rather be a service provided by thecontainer. It leads to overwhelming complexity of both the specifi-cation and applications using it. EJB entity beans were widely usedtechnology, but due to its complexity and general unhappiness withthe specification, companies were often forced to create various pro-prietary persistence solutions. Several open-source frameworks have

    also been created, with Hibernate being the most widely used one.EJB entity beans are for backward compatibility still present in the

    Java EE specification, so every Java EE compliant application server

    7. By primitive properties I mean properties of primitive data types, which aredirectly supported by database systems.

    10

  • 7/29/2019 Perbandingan berbagai Provider JPA

    16/58

    1. INTRODUCTION

    has to support it. They are, however, considered as deprecated in

    favour of the new JPA specification.

    1.3.3 JDO

    With a rising frustration from EJB entity beans, there was an attemptto come with an alternative; with a new persistence specification,which would work with POJOs8 and finally abandon the concept ofcontainer-managed persistence. This specification is called Java DataObjects. Even though JDO is quite powerful, in some aspects evenmore powerful than its successor, JPA9; it failed to get larger popu-

    larity among developers and become the mainstream. JDO requiresbyte-code manipulation to enhance persistent classes and, therefore,is quite complicated as well. Mike Keith ([7]) also claims, that oneof the reasons why JDO has failed is its inherently object-orientedquery language, which does not play well with programmers usedto relational databases.

    1.3.4 myBatis

    myBatis (formerly iBatis) is a lightweight persistence framework that

    gives the programmer full control over the SQL queries sent to thedatabase. It does not generate any SQL code; it merely maps customSQL statements to the properties of entities being stored in the data-base. Despite all the advantages and interesting ideas, it is not a full-blown persistence solution since it lacks features demanded from ageneral-purpose persistence framework, such as portability acrossdifferent database systems (all the SQL code is database-specific).Moreover, myBatis is not part of the Java EE specification, which alsomeans that it does not integrate with the rest of the Java EE ecosys-tem and, therefore, features like container-managed transaction han-dling, entity lifecycle callbacks or JSR-303 Bean Validation are notsupported.

    8. Abbreviation of Plain Old Java Object, denoting ordinary Java classes whichdo not follow any special conventions or framework rules (http://www.martinfowler.com/bliki/POJO.html ).9. JDO for example supports non-relational data stores, whereas JPA does not.

    11

    http://www.martinfowler.com/bliki/POJO.htmlhttp://www.martinfowler.com/bliki/POJO.htmlhttp://www.martinfowler.com/bliki/POJO.htmlhttp://www.martinfowler.com/bliki/POJO.htmlhttp://www.martinfowler.com/bliki/POJO.html
  • 7/29/2019 Perbandingan berbagai Provider JPA

    17/58

    1. INTRODUCTION

    1.4 JPA

    EJB 3 specification, as part of completely reworked Java EE 5, re-leased in 2006, contained a new specification regarding persistence Java Persistence API10. JPA was a response to users increasing frus-tration with the complexity of EJB 2.x entity beans. Authors of pro-prietary persistence frameworks and other experts were invited tosit in groups working on a brand new Java persistence specification,which would replace EJB entity beans.

    JPA2 (included in Java EE 6, released in 2009) is an evolution ofJPA. It is based on the experience with JPA and reflects users critique

    (mostly about missing features which are already present in otherproprietary persistence frameworks). In this text I will only focus onJPA2 specification and its features11.

    1.5 Goals of the thesis

    In this thesis, I will:

    Compare three different JPA implementations and build a fea-ture matrix showing their strengths and weaknesses.

    Take an open source project written in each JPA implementa-tion, migrate it to the other two, test it on Oracle, PostgreSQLand MySQL and document the issues I run into during themigration process.

    Build a migration tool, which will provide a support with mi-grating OpenJPA and EclipseLink projects to Hibernate.

    10. In Java EE 5, the JPA specification is formally a part of the EJB 3 specifica-tion. The decision to bind them together was probably quite unfortunate, though,because JPA is not in any means dependent on EJB container and thus works per-fectly fine in Java SE environments. JPA2 is separate specification already, formallyindependent of EJB.11. From this point on, wherever I use JPA, I mean JPA2 specification. I will usethe term JPA2 only to emphasise that a particular feature was introduced in thenew JPA2 standard.

    12

  • 7/29/2019 Perbandingan berbagai Provider JPA

    18/58

    2 Comparison of JPA providers

    JPA2 is a persistence standard for the Java platform defined by SunMicrosystems in [8]. The JPA specification itself does not containany usable code; it only describes persistence concepts and providesstandard interfaces, which all standard-compliant frameworks areobliged to implement. Reference implementation of this specificationis EclipseLink1.

    Currently there are three main implementations of JPA: Hiber-nate, EclipseLink and OpenJPA. I was unable to find any reliablestatistics about their popularity and market share, but consideringthat all of them are bundled with popular application servers2 andthus are in production use, it makes sense to compare them and tryto find out which one provides the most interesting features.

    2.1 Methodology of the comparison

    Comparing JPA providers is a tricky task. Since every single JPA im-plementation has to obey the standard and implement everythingthat the standard defines, it might lead to an incorrect conclusion

    they are all the same. This is up to some point true; within the bound-aries defined by the standard they are all equal. However, each JPAimplementation provides features that go beyond the scope of theJPA standard. These vendor-specific features extend the frameworksfunctionality in various areas.

    I have divided the features that go beyond the scope of the JPAstandard into several categories. I will go through all the categoriesand describe what features does the particular implementation offerand which possible alternatives do the others have. In the end, I willcreate a summary in form of a short feature matrix summing up theresults of the comparison.

    I will mainly focus on features, which are directly related to theJPA and extend it in some way. Therefore, I will not discuss for exam-

    1. http://www.eclipse.org/eclipselink/downloads/ri.php2. EclipseLink is used in as default JPA provider in GlassFish, OpenJPA in Geron-imo and Hibernate in JBoss AS.

    13

    http://www.eclipse.org/eclipselink/downloads/ri.phphttp://www.eclipse.org/eclipselink/downloads/ri.php
  • 7/29/2019 Perbandingan berbagai Provider JPA

    19/58

    2. COMPARISON OF JPA PROVIDERS

    ple a support of EclipseLink for non-relational data stores, because

    it is not a JPA extension but merely an additional capability of theframework.

    In order to guarantee a fair comparison, I will work with latestversions of all frameworks; at the time of writing, the latest stableversions available are Hibernate 4.0.0, EclipseLink 2.3.2 and Open-JPA 2.1.1.

    2.2 Identifier generation

    The JPA standard defines 4 primary key generation strategies3 (table,sequence, identity and auto). All frameworks from the comparison,however, provide additional ways to generate identifiers.

    In Hibernate, there is an annotation @GenericGenerator creat-ing a non-standard ID generator. Its parameter is either a fully-qualifiedname of a class implementing IdentifierGenerator or a shortcutof one of the many predefined generators from the Hibernate distri-bution, such as increment, identity, sequence, hilo, uuid, guid andothers. Since Hibernate version 3.2.3, the preferred way of generatedidentifiers is using TableGenerator and SequenceStyleGenerator,due to better optimization and database portability[9]4.

    OpenJPA also allows creating user-defined identity generatorsby implementing Seq interface[10]5. Besides the standard ones, theOpenJPA distribution contains few additional generators, most in-sterestingly TimeSeededSeq generating identifiers based on systemtime and UUIDHexSeq generating random hex strings.

    In EclipseLink, it is possible to create custom generators by ex-tending Sequence and registering the generator class in persistenceunit configuration (persistence.xml) as follows:

    ...

    com.example.eclipiselink.CustomIdGenerator

    3. JavaTMPersistence API, Version 2.0, section 11.1.174. Hibernate developer guide, section 28.45. OpenJPA users guide, section 9.6

    14

  • 7/29/2019 Perbandingan berbagai Provider JPA

    20/58

    2. COMPARISON OF JPA PROVIDERS

    ...

    The distribution contains QuerySequence an implementation ofSequence, which is not only the parent of all the standard sequencegenerators contained in the EclipseLink distribution, but also servesas an generic mechanism for obtaining identifiers using user-definedqueries [11].

    2.3 Performance

    Good performance is indeed a fundamental requirement from anypersistence solution. In this chapter I will benchmark all the frame-works being compared and measure how fast do they perform invarious usage scenarios.

    For the purpose of this benchmark, I created a sample JPA appli-cation that contains several entities, which are mapped to the data-base schema from diagram 2.1.

    Figure 2.1: ER diagram of sample database schema

    Thepersistence.xmlconfiguration file contains several persistenceunits; each one configured with different data source and differentJPA provider. The application also contains a simple testing frame-work, which is in charge of creating an EntityManagerFactory for a

    15

  • 7/29/2019 Perbandingan berbagai Provider JPA

    21/58

    2. COMPARISON OF JPA PROVIDERS

    particular persistence unit, initializing6 and running tests, measuring

    execution times and logging the results.In the benchmark, I will test how the frameworks perform in the

    default configuration, without any vendor-specific optimizations. Eachtest will be executed three times and the average time will be pre-sented as the test result. All test will run on the following configura-tion:

    Intel Core2 Quad Q9400 2.66GHz

    4GB RAM

    Xubuntu Linux 11.10, 64-bit

    Oracle JDK 7

    PostgreSQL 9.1.3

    JDBC4 driver, version 9.1-901

    To guarantee that tests of all frameworks run under the same con-ditions7, I disabled automatic schema generation and created it man-ually, as shown in listing 2.1.

    create sequence sample_sequence start 1000 increment50;

    create table "user" (

    user_id bigint primary key,

    username varchar(32) not null unique,

    enabled boolean not null default true);

    create table users_authorities (

    user_id bigint references "user",

    name varchar(32) not null);

    6. Some tests need data already present in the database. Required INSERT state-ments are, therefore, executed in the initialization phase, the duration of which isnot included in the test result.7. As seen in appendix A.2, OpenJPA generates some additional indexes, whichwould need to be updated with each insert and, therefore, tests execution timeswould be affected.

    16

  • 7/29/2019 Perbandingan berbagai Provider JPA

    22/58

    2. COMPARISON OF JPA PROVIDERS

    create table discussion (

    discussion_id bigint primary key);

    create table article (

    article_id bigint primary key,

    created timestamp default now(),

    headline text,

    content text,

    discussion_id bigint not null unique references

    discussion);

    create table users_articles (

    user_id bigint references "user" (user_id),

    article_id bigint references article);

    create table tag (

    tag_id bigint primary key,

    name varchar(32) not null unique);

    create table articles_tags (

    article_id bigint not null references article,

    tag_id bigint not null references tag);

    create table post (

    post_id bigint primary key,

    created timestamp not null default now(),

    author varchar(32),

    title varchar(32),

    text text);

    create table discussions_posts (

    discussion_id bigint not null references

    discussion,

    post_id bigint not null unique references post);

    Listing 2.1: DDL defining sample database schema

    In following sections, I will present results of the performancebenchmarks.

    17

  • 7/29/2019 Perbandingan berbagai Provider JPA

    23/58

    2. COMPARISON OF JPA PROVIDERS

    2.3.1 Batch inserts

    First executed test is benchmarking batch inserts. I persist 10,000 in-stances ofUser entity8. The results are presented in table 2.1.

    1 2 3 AverageHibernate 467 8ms 4744 ms 4768 ms 4730 msOpenJPA 4348 2ms 44779 ms 45813 ms 44691.33 ms

    EclipseLink 3799 ms 3832 ms 3825 ms 3818.67 ms

    Table 2.1: Batch inserts on PostgreSQL test results

    From the values in the table 2.1, we can see that EclipseLink wasthe fastest, with Hibernate being the second. OpenJPA, on the otherhand, scored more than 10 times worse. Since such result is very sur-prising, I decided to run the exact same test on the same machine, butnow with MySQL database9. The result are presented in table 2.2.

    1 2 3 AverageHibernate 5128 ms 5042 ms 5137 ms 5132.33 msOpenJPA 10790 ms 10696 ms 10617 ms 10701 ms

    EclipseLink 3377 ms 3257 ms 3387 ms 3340.33 ms

    Table 2.2: Batch inserts on MySQL test results

    We can see that the difference is not so big anymore, but Open-JPA still performs much worse than the others. There are some per-formance optimizations available to tune OpenJPA for batch opera-tions, but in the default configuration its performance was by far theworst of all compared frameworks.

    2.3.2 Searching by ID

    In this test I make use of the values inserted by previous test. From10,000 user inserted I fetch by ID random 1,000 of them. Results arepresented in table 2.3.

    8. Users are persisted with an auto-generated name and no articles attached.9. The version of MySQL server used in the test was 5.1.61.

    18

  • 7/29/2019 Perbandingan berbagai Provider JPA

    24/58

    2. COMPARISON OF JPA PROVIDERS

    1 2 3 Average

    Hibernate 828 ms 863 ms 756 ms 815.66 msOpenJPA 5285 ms 5155 ms 5227 ms 5222.33 ms

    EclipseLink 691 ms 683 ms 666 ms 680 ms

    Table 2.3: Find by ID test results

    2.3.3 Basic JPA QL test

    In this test I fetch all users stored in the database using JPA query.Table 2.4 presents the results.

    1 2 3 AverageHibernate 1002 ms 1138 ms 1013 ms 1051 msOpenJPA 1196 ms 1086 ms 1078 ms 1120 ms

    EclipseLink 1110 ms 1133 ms 1256 ms 1166.33 ms

    Table 2.4: Fetch all users using JPA QL test results

    2.3.4 Basic criteria API testThis test is in its nature similar to the previous one, but I fetch allusers using Criteria API instead of JPA QL. Criteria API is a newfeature introduced in JPA2. Results are presented in table 2.5.

    1 2 3 AverageHibernate 1567 ms 1530 ms 1523 ms 1540 msOpenJPA 1054 ms 1094 ms 1136 ms 1094.66 ms

    EclipseLink 882 ms 764 ms 862 ms 836 ms

    Table 2.5: Fetch all users using criteria API test results

    Interesting observation from these results is, that Hibernate per-forms significantly slower when using criteria API instead of JPA QL,whereas EclipseLink, on the other hand, performs slightly faster. Re-sults of OpenJPA are about the same.

    19

  • 7/29/2019 Perbandingan berbagai Provider JPA

    25/58

    2. COMPARISON OF JPA PROVIDERS

    2.3.5 Aggregate function

    In this test I measure how fast counting entities using both JPA QLand criteria API is. In the test initialization phase, 1,000 users are in-serted into the database, but only half of them have their account setas enabled. Each user has 15 articles and each article has 3 comments.In the test itself, I perform complex join over User, Article, Discussionand Post tables, then selection by Users enabled property and countreturned entities. Results are presented in tables 2.6 and 2.7.

    From the results presented in the tables below, it is interesting tosee that the same query is significantly faster using the criteria API

    than using standard JPA query.

    1 2 3 AverageHibernate 306 ms 250 ms 245 ms 267 msOpenJPA 354 ms 400 ms 407 ms 387 ms

    EclipseLink 306 ms 295 ms 349 ms 316.66 ms

    Table 2.6: Complex join using JPA QL test results

    1 2 3 AverageHibernate 127 ms 115 ms 100 ms 114 msOpenJPA 176 ms 178 ms 177 ms 177 ms

    EclipseLink 104 ms 107 ms 104 ms 105 ms

    Table 2.7: Complex join using criteria API test results

    2.3.6 Performance summary

    From the test results presented, EclipseLink is more or less on parwith Hibernate. Out of seven executed tests, EclipseLink took thefirst place five times and Hibernate two times. OpenJPA, on the otherhand, performs the worst in all tests except two. Especially in batchinsert test, its performance is far behind the competitors. In othertests the results were quite similar. Therefore, the poor performanceof applications using JPA it is more likely caused by a poor database

    20

  • 7/29/2019 Perbandingan berbagai Provider JPA

    26/58

    2. COMPARISON OF JPA PROVIDERS

    design or incorrect use of the persistence framework (e.g. construc-

    tion of queries which demand complex join, etc.); not by the frame-work itself.

    It is important to note that all the frameworks are highly con-figurable and offer various performance enhancements for specificusage-scenarios. Therefore, it is important not to overestimate the re-sults of this benchmark. It does provide, however, some view on theperformance of compared JPA implementations in default configu-rations.

    2.4 Type conversion

    JPA specification does not define any kind of type conversion. Forexample, if in the database there is a string field which stores booleanvalues as Y and N strings, there is no way to map it (directly) to aJava boolean. All JPA implementations, however, provide extensionswhich allow map various database types to Java types and also allowcreating user-defined types.

    In Hibernate, there is a Type interface. All the types Hibernate

    recognizes implement this interface. So, in Hibernate there are classeslike CalendarType mapping Calendar to a datetime, ClassType,which maps Java Class objects to varchars, etc. However, for creat-ing new custom types, it is generally not recommended to implementType directly because it would make custom type converters tightlycoupled with the Type interface and future changes (such as addedor removed methods) would break all custom type converters [12].For this reason, there is an interface UserType that should be usedfor creating custom type converters, which are later adapted to Typeusing CustomType.

    OpenJPA also provides support for creating custom mappings.There is an interface ClassStrategy which can be used for creatingmapping between custom classes and database schema. Such classstrategy can be then configured using @Strategy mapping anno-tation. For creating various custom field mappings, OpenJPA pro-vides ValueHandler and FieldStrategy interfaces. The latter is abit more complicated to implement, but provides more flexibility

    21

  • 7/29/2019 Perbandingan berbagai Provider JPA

    27/58

    2. COMPARISON OF JPA PROVIDERS

    when interacting with the database10.

    Since creating custom field strategies might be in many cases overlycomplicated, especially when quite simple value transformation areneeded, OpenJPA provides a mechanism called externalization. Us-ing the @Externalizer annotation, we might specify either an in-stance method of the mapped class or a static method of any classwhich should be invoked to transform a value to its database repre-sentation. Its counterpart is a @Factory annotation, which specifieshow the transformation from the database representation to the cus-tom type looks like. We might pass either nothing, or an instancemethod name of the custom type of any static method which does

    the conversion. In case that nothing is passed, the constructor of thecustom type is invoked.

    In EclipseLink, the primary interface for defining custom convert-ers is Converter. Applications can either create custom implementa-tions of this interface or use some of the predefined converters fromthe EclipseLink distribution. Some examples of the predefined con-verters are [13]:

    ObjectTypeConverter is the simplest converter available. It is usedfor custom mapping of database values to Java values whenthe formats differ

    TypeConversionConverter can be used for explicit mapping of datasource types to Java types

    SerializedObjectConverter maps various binary formats into data-base BLOBs.

    When a proper converter is configured, it can be attached to themapped attribute using the @Convert annotation.

    2.5 Caching support

    The JPA2 specification comes with basic support for second-levelcache11. Second-level cache is the cache at the EntityManagerFactory-level, so it contains entities from multiple persistence contexts.

    10. OpenJPA users guide, section 7.10.3.211. JavaTMPersistence API, Version 2.0, section 3.7

    22

  • 7/29/2019 Perbandingan berbagai Provider JPA

    28/58

    2. COMPARISON OF JPA PROVIDERS

    Caching can be using shared-cache-modeconfiguration property

    in persistence.xml. Possible values are:

    ALL

    NONE

    ENABLE SELECTIVE

    DISABLE SELECTIVE

    UNSPECIFIED

    There is also the @Cacheable annotation used for specifying entity-

    level caching mode in case that either ENABLE SELECTIVE or DIS-ABLE SELECTIVE global caching has been set. In case of UNSPECI-FIED cache mode setting, provider-specific rules apply. Since cachingis handled in such minimalistic and rather abstract way, various vendor-specific extensions exist.

    The approach recommended in Hibernate the documentation isdelegating the caching functionality to specialized caching tools12.Thus, Hibernate neatly integrates with the most popular caching frame-works like EhCache of Hazelcast, simply by setting the configura-tion property hibernate.cache.region.factory class to an appropriatecache region factory of the selected caching framework.

    OpenJPA comes with its own data cache implementation13, it canbe turned on using openjpa.DataCacheconfiguration property. Open-JPA also contains transaction-events notification framework14, whichcan be used for cache synchronization between nodes in distributedenvironment.

    EclipseLink also contains integrated second level cache imple-mentation and does not rely on any third-party framework. Like inOpenJPA, it also supports caching in clustered environment; usingconfiguration property eclipselink.cache.coordination.protocol it ispossible to specify which protocol should be used for cache coordi-

    nation between nodes. Possible options described in the documenta-tion [13] are RMI and JMS.

    12. Hibernate developer guide, section 21.213. There is a plug-in integrating EhCache with OpenJPA, but since it is not evenmentioned in the official documentation, I will not further discuss it.14. OpenJPA users guide, section 12.2

    23

  • 7/29/2019 Perbandingan berbagai Provider JPA

    29/58

    2. COMPARISON OF JPA PROVIDERS

    To sum up caching solutions used in JPA implementations; Hi-

    bernate tries to delegate caching to specialized tools, whereas Open-JPA and EclipseLink integrate second level caching into the core ofthe framework. The undeniable advantage of Hibernates approachis that it that it does not try to reinvent the wheel. Since specializedcaching frameworks are already mature and sophisticated, it is gen-erally a good idea to utilize them as general second-level JPA cachesolutions. Slight disadvantage, however, is that third-party frame-work is required, which might increase the overall complexity of thearchitecture.

    2.6 Entity lifecycle and transactional events

    JPA specification defines seven entity lifecycle events: pre/post-persist,pre/post-remove, pre/post-update and post-load; and 2 ways of lis-tening to such events - either by adding appropriate lifecycle an-notation on entity method or specifying an EntityManagerFactory-scoped callback listener15. Even though these callbacks should be finein most cases, all vendors provide alternative ways of listening toevents in the persistent layer.

    Hibernate has the concept of interceptors16. Interceptors can be

    either Session-scoped or SessionFactory-scoped and provide someadditional callbacks, but with the limitation that there can be onlyone per Session/SessionFactory. Hibernate also contains event archi-tecture, which is superior to interceptor capabilities and can be usedto listen to even more fine-grained events raised by the Hibernatesession. All supported events are contained in EventType enum.

    OpenJPA support listening to transaction-related events via in-stances ofTransactionListener interface. Such instances are regis-tered at OpenJPAEntityManagerSPI, an OpenJPA-specific extensionofEntityManager. Besides transaction-related events, it is also pos-

    sible to register LifecycleListener which supports additional call-backs to those from JPA2 standard, such as DetachListener for no-tification when an entity becomes detached [14]. However, the doc-umentation does not mention this interface at all, so it might not be

    15. JavaTMPersistence API, Version 2.0, section 3.516. Hibernate developer guide, section 14

    24

  • 7/29/2019 Perbandingan berbagai Provider JPA

    30/58

    2. COMPARISON OF JPA PROVIDERS

    intended for public use or might be changed in future releases.

    EclipseLink, on the other hand, contains support for events whichoccur in the session (EclipseLink-specific implementation of Entity-Manager). There is an interface SessionEventListener, which canbe registered with a session for getting notification about followingsession-related events:

    pre/post-transaction commit

    pre/post-transaction rollback

    pre/post-query execution

    the descriptor for an entity being persisted is missing

    ...

    2.7 Schema generation

    In order to keep the specification clean and simple17, JPA does notforce vendors to generate database schema18. However, the authorsof the specification took schema generation into an account and inte-grated various metadata mappings, which can be used during schemageneration, such as nullable or unique annotation properties.

    All the compared implementations provide a schema generationfunctionality. Generated statements can either be sent directly to thedatabase or saved into a file for manual execution. Also DROP state-ments can be generated, so during development it is possible to haveall tables removed and generated again on each startup. This en-sures that the application always starts in the same state with anempty database. However, even though automatic schema gener-ation might be convenient in the development phase, it is often a

    17. Another reason why the specification does not contain any details of theschema generation is that it is very vendor-specific issue. The specification wouldhave to describe how tables generated from entities should look like on particu-lar database platform, which datatypes or constraints should be used, etc. Sinceall these elements differ from database to database very much, the specificationavoids it entirely.18. JavaTMPersistence API, Version 2.0, page 355

    25

  • 7/29/2019 Perbandingan berbagai Provider JPA

    31/58

    2. COMPARISON OF JPA PROVIDERS

    source of problems when dealing with incremental schema upgrades.

    Therefore, it is generally recommended to avoid it in production en-vironments when possible and rather use database migration toolslike Liquibase19, Flyway20 or MyBatis migrations21.

    In Hibernate, it is possible to turn on schema generation usingconfiguration property hibernate.hbm2ddl.auto, which can be set toone of the following values: validate, update, createand create-drop.Then, before the EntityManagerFactory is created, Hibernate gener-ates DDL statements and executes them on the database. If this is notthe desired behaviour, there is a SchemaTool class in the Hibernatedistribution, which is responsible for generating the schema and can

    be executed manually (either programatically or via command-line)to have DDL statements generated into a file.

    OpenJPA can also be configured to automatically generate the da-tabase schema on the application startup by setting configurationproperty openjpa.jdbc.SynchronizeMappings to buildSchema. Likein Hibernate, the schema generation can be triggered manually us-ing MappingTool utility. However, OpenJPA goes even further inthis area and, as the only one from the compared implementations,also allows generating an object model from an existing databaseschema22. This feature is usually only provided by advanced UML

    modelling tools, such as Enterprise Architect from Sparx systems23

    .In EclipseLink, the schema generation can be turned on usingpersistence.xml property eclipselink.ddl-generation. There is also anoption to have DDL statements not only executed directly on the da-tabase, but also export them into a file. This is done by setting theconfiguration property eclipselink.create-ddl-jdbc-file-nameto a tar-get file path and eclipselink.ddl-generation.output-modeto both.

    In appendix A, I provide DDL statements of the schema used inthe sample benchmark application from chapter 2.3, automaticallygenerated by Hibernate, OpenJPA and EclipseLink, respectively.

    19. http://www.liquibase.org/20. http://code.google.com/p/flyway/21. http://code.google.com/p/mybatis/22. OpenJPA users guide, section 7.223. http://www.sparxsystems.com.au/

    26

    http://www.liquibase.org/http://code.google.com/p/flyway/http://code.google.com/p/mybatis/http://www.sparxsystems.com.au/http://www.sparxsystems.com.au/http://code.google.com/p/mybatis/http://code.google.com/p/flyway/http://www.liquibase.org/
  • 7/29/2019 Perbandingan berbagai Provider JPA

    32/58

    2. COMPARISON OF JPA PROVIDERS

    2.8 Support for stored procedures

    A stored procedure is a group of SQL statements that is used toencapsulate a set of operations or queries to execute on a databaseserver[15].

    JPA standard doesnt mention stored procedures support at all.However, stored procedures are executed using ordinary SQL, so aslong as the stored procedure returns nothing or a result set (which isproperly mapped to entities using @SqlResultSetMapping on theJPA side24), it can be called using JPA native queries with all JPAproviders. EclipseLink, however, contains some additional, beyond-

    the-standard features for accessing stored procedures [13].Lets consider following very simple MySQL stored procedure:

    CREATE PROCEDURE calculate_item_count(OUT result INT)

    BEGIN

    select count(item_id) into result from Item;

    END

    Listing 2.2: Sample stored procedure

    The stored procedure does nothing else than calculating the num-ber of items in table Item and storing it in an output parameter result.

    In EclipseLink, it is possible to call stored procedure using Stored-ProcedureCall as follows:

    EntityManager em = emf.createEntityManager();

    StoredProcedureCall spc = new StoredProcedureCall();

    spc.setProcedureName("calculate_item_count");

    spc.addNamedCursorOutputArgument("result");

    em.getTransaction().begin();

    Session s = em.unwrap(Session.class);

    s.executeSelectingCall(spc);

    em.getTransaction().commit();

    Using this approach, it is not necessary to deal with SQL directlyin stored procedure calls; the procedure is executed by its name only.

    Except the StoredProcedureCall, EclipseLink also provides annotation-based approach, similar to the named queries. Using the annota-

    24. JavaTMPersistence API, Version 2.0, section 3.8.15

    27

  • 7/29/2019 Perbandingan berbagai Provider JPA

    33/58

    2. COMPARISON OF JPA PROVIDERS

    tion @NamedStoredProcedureQuery, it is possible to define named

    stored procedure call, which can be later executed in similar mannerlike standard @NamedQuery or @NamedNativeQuery:

    Query query = entityManager.createQuery("queryName");

    query.getResultList();

    So, having defined the stored procedure from listing 2.2, the namedstored procedure call definition would look as follows:

    @NamedStoredProcedureQuery(

    name = "getItemCount",

    procedureName = "calculate_item_count",parameters =

    @StoredProcedureParameter(queryParameter =

    "result", name = "result", direction =

    Direction.OUT))

    EclipseLink has the best support of stored procedures from allcompared JPA implementations. Using Hibernate, the named nativequery definition for stored procedure call would look like this:

    @NamedNativeQuery(name = "getItemCountHibernateWay",

    query = "? = call calculate_item_count()")

    However, this code for procedure calculate item count, as definedin listing 2.2, would fail because Hibernate does not yet support na-tive scalar queries; the code would lead to NotYetImplementedEx-ception.

    OpenJPA also claims support of stored procedures25, but I wasunable to get running any.

    2.9 Integrating with other frameworks

    Another important decision factor for choosing a JPA implementa-tion is its support for other frameworks which would extend its ca-pabilities even further.

    25. It is very briefly mentioned in the documentation, without any examples orfurther details.

    28

  • 7/29/2019 Perbandingan berbagai Provider JPA

    34/58

    2. COMPARISON OF JPA PROVIDERS

    Hibernate is known for an excellent integration with various third-

    party frameworks. Hibernate is not just a persistence framework, itis sort of an ecosystem with many frameworks built around Hiber-nate ORM. In chapter 2.5, I was already discussing its integrationwith caching frameworks like EhCache or Hazelcast. Two anotherimportant and useful extensions are Hibernate Search and HibernateValidator.

    Hibernate Validator is a reference implementation of the speci-fication JSR 303: Bean Validation [16]. JSR 303 a standard API fordeclarative validations, which JPA already supports for validatingentities upon lifecycle events26. The configuration is done via prop-

    erty javax.persistence.validation.mode in persistence.xml. The pos-sible values are AUTO, CALLBACK or NONE. Hibernate providesan additional option DDL.

    When the value of this property is set either to AUTO or DLLand Bean Validation is present in the classpath, the validation meta-data are also used in schema generation. When an entity attribute isdecorated with one of the supported annotations from this specifica-tion, Hibernate reflects such a validation constraint in the generatedschema. For example, if an attribute of type long is annotated withJSR-303 annotation @Max(30), Hibernate schema generator adds a

    database check constraint to ensure that values in the column areless or equal to 30. There are more supported JSR-303 annotations,such as @Min, @NotNull, @Size, etc. [17]27

    Hibernate Search is a framework built on top of Apache Luceneaiming to provide full-text search capabilities to the domain model.It works with both native Hibernate API and Hibernate EntityMan-ager.

    2.10 Licenses

    When a company is considering implementing their enterprise so-lution on top of some ORM framework, the character of its licenseis very important. Fortunately, all of the compared frameworks arereleased under permissive and business-friendly licenses. Hibernate

    26. JavaTMPersistence API, Version 2.0, section 3.627. Hibernate Validator reference documentation, section 2.4.1

    29

  • 7/29/2019 Perbandingan berbagai Provider JPA

    35/58

    2. COMPARISON OF JPA PROVIDERS

    uses LGPL v2.128 OpenJPA uses Apache License v2.029 and Eclipse-

    Link is dual licensed under Eclipse Public License - v1.0 and EclipseDistribution License v1.030. Dual license means that users can choosewhich license suits their business needs best.

    2.11 Documentation quality

    During my work on this thesis I was extensively reading the docu-mentation on each particular topic discussed here and, therefore, I

    am eligible to provide some comparison of the documentation qual-ity of all the frameworks.

    Hibernate has a high-quality documentation. With every new ver-sion of the framework, there is a new document describing its fea-tures, it is possible to find documentation of older releases and ev-erything is clearly explained with examples. Since Hibernate is themost widely used implementation, there is also a lot of examples allover the internet and users can ask questions in discussion forums31.

    OpenJPA also has high-quality documentation, everything is pos-sible to find there. However, it is unfortunately not as example-rich

    as in Hibernate; it is purely a reference guide. As every Apache project,OpenJPA provides mailing lists for users questions.

    For EclipseLink, there is quite a lot of documentation, but its prob-lem is the fragmentation. Indeed, it is possible to find answers tomost of the questions, but it took me significant amount of time com-pared to Hibernate or OpenJPA. Moreover, since the documentationis not versioned, it is sometimes fairly difficult to distinguish whichfunctionality is new to EclipseLink implementation of JPA2 and whichwas already present in EclipseLink JPA1. EclipseLink also has itssupport forums32.

    28. http://www.hibernate.org/license29. http://openjpa.apache.org/license.html30. http://wiki.eclipse.org/EclipseLink/FAQ/General31. http://forums.hibernate.org32. http://www.eclipse.org/forums/index.php/f/111

    30

    http://www.hibernate.org/licensehttp://openjpa.apache.org/license.htmlhttp://wiki.eclipse.org/EclipseLink/FAQ/Generalhttp://forums.hibernate.org/http://www.eclipse.org/forums/index.php/f/111http://www.eclipse.org/forums/index.php/f/111http://forums.hibernate.org/http://wiki.eclipse.org/EclipseLink/FAQ/Generalhttp://openjpa.apache.org/license.htmlhttp://www.hibernate.org/license
  • 7/29/2019 Perbandingan berbagai Provider JPA

    36/58

    2. COMPARISON OF JPA PROVIDERS

    2.12 Build systems

    Nowadays, Maven can be considered as the industry de-facto stan-dard build and project management tool. EclipseLink and OpenJPAboth use it for their builds. Hibernate in version 4.0, however, hasswitched to Gradle, which is a build tool written in Groovy. Hiber-nate creators switched to Gradle hoping to simplify the build processand get rid of other various build-related problems 33.

    2.13 Summary

    In this section I discussed various vendor-specific extension of theJPA standard. I summarize this chapter in following brief feature-matrix:

    Hibernate OpenJPA EclipseLinkCustom identifier genera-tion

    Yes Yes Yes

    Performance in the defaultconfiguration

    2. 3. 1.

    Build-in event notificationframework

    Powerful Yes Yes

    Support for custom types Yes Yes YesSchema generation Yes Powerful YesCaching Third-party Custom CustomNonstandard stored proce-dures support

    No No Yes

    Third-party frameworkssupport

    Yes No No

    Documentation quality High High ModerateBusiness-friendly license Yes Yes Yes

    Table 2.8: Feature matrix

    It is important to note that the list of features presented in thischapter is by no means exhaustive; I just described important fea-

    33. Deeper explanation of the reasons behind the transition to Gradle can be foundat https://community.jboss.org/wiki/GradleWhy .

    31

    https://community.jboss.org/wiki/GradleWhyhttps://community.jboss.org/wiki/GradleWhy
  • 7/29/2019 Perbandingan berbagai Provider JPA

    37/58

    2. COMPARISON OF JPA PROVIDERS

    tures which are most likely to be used in real-world applications

    using JPA. All implementations contain additional, more or less corner-case features or performance enhancements, the description of whichwould be beyond the scope of this thesis.

    32

  • 7/29/2019 Perbandingan berbagai Provider JPA

    38/58

    3 Experimental migration of JPA applications

    In this chapter, I will take sample applications of all compared imple-mentations, migrate them to the other two and test it on PostgreSQL,MySQL and Oracle. I will try to use standard features where possi-ble and fall back to vendor-specific extensions only when necessary.Features, which are neither possible to migrate to the standard API,nor have they counterparts in the other frameworks, will be removedentirely.

    All migrated projects were tested on MySQL 5.5.22, PostgreSQL9.1.3 and Oracle XE 11.2. Since all the projects use automatic schemageneration, there were not real issues with the database portability;the only exception was identifier generation. Both PostgreSQL andOracle support sequences, so I could use sequence generation strat-egy there. In MySQL, however, due to the missing support of se-quences, I had to switch to the table generation strategy1.

    3.1 Migrating from Hibernate

    Since Hibernate does not ship with any official reference applica-

    tion, I searched at SourceForge

    2

    for some projects using Hibernate,which would be suitable candidates for experimental migration. Inthe end, I decided for open-forum3 because it is already managed byMaven and has convenient and easily understandable project struc-ture. Open-forum describes itself as an opensource forum enginewritten in Java. The project is not yet finished, quite a lot of func-tionality is still not implemented, but as an example project for ex-perimental migration it is fine.

    Open-forum uses Spring framework, JSF2 and Hibernate. Inter-esting fact is that it does not use JPA at all, but rather relies on thenative Hibernate API. Therefore, it will be necessary to migrate com-

    plete persistence logic to the standard API. The project also depends

    1. I might have chosen AUTO generation strategy, which automatically deter-mines the right one for the particular database, but since I prefer to have controlover what is going to be generated, I configured the generation strategy manually.2. http://www.sourceforge.net/3. http://sourceforge.net/projects/open-forum/

    33

    http://www.sourceforge.net/http://sourceforge.net/projects/open-forum/http://sourceforge.net/projects/open-forum/http://www.sourceforge.net/
  • 7/29/2019 Perbandingan berbagai Provider JPA

    39/58

    3. EXPERIMENTAL MIGRATION OF JPA APPLICATIONS

    on Hibernate Search, but the searching functionalities are not yet im-

    plemented. If they were, however, it wouldnt be possible to migratethe project at all, because Hibernate Search does not work with anyother JPA providers except Hibernate, as I already discussed in sec-tion 2.9.

    The migration of this project consists of following steps:

    Entirely remove Hibernate dependency from the Maven con-figuration file.

    Modify Spring configuration files to bootstrap the JPA entitymanager factory instead of the Hibernate session factory. Thisis done via LocalContainerEntityManagerFactoryBeanbeandefined in the Spring application context.

    Change Hibernate-specific entity annotations. Since the projectwas already using many standard annotations from packagejavax.persistence where possible, it was only necessary tomigrate the @LazyCollection annotation, which I replacedwith the fetch attribute of corresponding @ManyToMany an-

    notations.

    Replace classes from the native Hibernate API, such as Queryor Session, with its standard counterparts.

    Rewrite HQL queries because their syntax in some aspects dif-fers from the JPA QL.

    Create persistence.xml configuration file and properly define

    a new persistence unit and its properties.

    Migration of this project was went without any serious complica-tions. It was even not necessary to use any vendor-specific extensions(with the exception of different configuration property for schemageneration).

    34

  • 7/29/2019 Perbandingan berbagai Provider JPA

    40/58

    3. EXPERIMENTAL MIGRATION OF JPA APPLICATIONS

    3.2 Migrating from OpenJPA

    Unlike Hibernate, for OpenJPA there are two sample applicationsavailable at its website4 OpenBooks and OpenTrader. I first triedto migrate OpenTrader, which is a GWT web application. Unfortu-nately, I was unable to get running even its original OpenJPA-basedversion, due to some GWT-related errors. Therefore, I will migrateOpenBooks in this section.

    Openbooks uses Maven for dependency management. Therefore,the first step of the migration process was removing all OpenJPA-related dependencies and adding Hibernate EntityManager. After

    I imported such project into the IDE and tried to compile it, I re-ceived more than a hundred of compilation errors. OpenBooks un-fortunately heavily relies on the native OpenJPA API.

    The next task was migrating JPA configuration in persistence.xml.I changed the provider of the persistence unit to Hibernate, removedOpenJPA-specific configuration options and replace them with theirHibernate counterparts when possible. The configuration options notapplicable in Hibernate, such as automatic enhancement of persis-tent classes, were removed entirely.

    Some errors were related to missing metamodel classes required

    for the type-safe criteria API

    5

    a new feature introduced in JPA2. Theoriginal OpenJPA-based project used an ANT task to generate suchclasses, so in its migrated version, I also had to generate such meta-model classes. There is a subproject of Hibernate called HibernateMetamodel Generator6 which provides an annotation processor ex-actly for this purpose. Metamodel generator can be run either as anANT task, Maven plugin or simply from the command line. Sincemy IDE supports triggering annotation processors on compile-time,I used the last option and thus didnt have to execute any ANT tasksor configure additional Maven plugins.

    Another group of compilation errors was complaining about miss-

    ing OpenJPA-specific classes on the classpath. Since the number ofmissing classes was very large and the application API was heavily

    4. http://openjpa.apache.org/samples.html5. JavaTMPersistence API, Version 2.0, section 6.46. http://www.hibernate.org/subprojects/jpamodelgen.html

    35

    http://openjpa.apache.org/samples.htmlhttp://www.hibernate.org/subprojects/jpamodelgen.htmlhttp://www.hibernate.org/subprojects/jpamodelgen.htmlhttp://openjpa.apache.org/samples.html
  • 7/29/2019 Perbandingan berbagai Provider JPA

    41/58

    3. EXPERIMENTAL MIGRATION OF JPA APPLICATIONS

    relying on them, I came to the conclusion that Openbooks applica-

    tion cannot be migrated to Hibernate (or any other JPA provider)without rewriting the major part of the code and reconsidering itsdesign concepts. It is simply not possible to replace missing Open-JPA classes with their alternatives from Hibernate, which would domore or less the same thing. OpenJPA-specific classes are distributedthroughout the application code, classes using them depend on an-other classes using them and removing a specific class or a methodfrom the application results in a large chain of broken dependencies.

    The lesson learned from the migration of Openbooks to Hiber-nate can be useful when designing new applications based on JPA. If

    there is even a slightest chance that it might be necessary to migratethe project to a different JPA provider in the future, the developersshould try hard to stick with the standard API and avoid vendor-specific extensions when possible. The migration process will likelybe painful and costly, because the native APIs of different JPA providersdo not work as simple replacements of each other. Each JPA providercomes with some concepts of its native API, which are not possibleto simply emulate in a different JPA provider.

    3.3 Migrating from EclipseLink

    As a sample application of migration from EclipseLink, I will usejpa.employeesample, which can be found at EclipseLink SVN repos-itory7. It is a project for focused on management of employees andprojects and is using JSF as frontend technology and EJB for the ser-vice tier. Its domain model is not very complicated but perfectly fineto show interesting JPA and EclipseLink features.

    In order to work with the application (and later with its migratedcopies) in a convenient way, I had first to polish it a bit (add Mavenfor builds and dependency management, refactor project structure,

    etc.). However, I was not able to successfully start the applicationon various application servers8 until I installed JBoss AS7, where thedeployment process was entirely painless.

    7. http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples

    8. I tried to run it on Glassfish and Apache TomEE

    36

    http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/exampleshttp://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/exampleshttp://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/exampleshttp://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples
  • 7/29/2019 Perbandingan berbagai Provider JPA

    42/58

    3. EXPERIMENTAL MIGRATION OF JPA APPLICATIONS

    Since the project is using container-managed datasource, there

    was no need to configure it in the application; I just configured thedatasource in the JBoss administration console9.

    During the migration, I had to rewrite or change the followingparts of the code:

    In this sample application, there was used EclipseLink-specificquery hint QueryHints.FETCH, which configures the queryto optimize the retrieval of the related objects, the related ob-jects will be joined into the query instead of being queried in-dependently [11]. Since there is no direct alternative in both

    Hibernate and OpenJPA, I removed this optimization hint en-tirely.

    There was a very EclipseLink-specific way of capturing loggedSQL statements (using Java reflection). I removed this code en-tirely and introduced a cleaner way of SQL statements loggingusing org.hibernate.LOG logger. In OpenJPA, there is a con-figuration property openjpa.Log, which is used for SQL state-ments logging.

    I had to remove eclipselink-orm.xml configuration file, which

    is also EclipseLink-specific. It contained various named querydefinitions (which I declared using annotations on entity-level),some additional persistence unit configuration and, most im-portantly, entity mapping metadata, which I added into enti-ties using the standard annotation-based approach.

    The application was saving gender field of employees in for-mat M and F for males and females, respectively. It was us-ing Eclipse-Link specific object-type-converterto convert suchstrings stored in the database into instances ofGender on theJava side. Since such conversion is not possible in pure JPA, Ihad to use vendor specific extensions of Hibernate and Open-JPA.

    9. I find such configuration very convenient, because it is no longer necessary tobundle database driver with the application; the application just expects that theconnection is there.

    37

  • 7/29/2019 Perbandingan berbagai Provider JPA

    43/58

    3. EXPERIMENTAL MIGRATION OF JPA APPLICATIONS

    In Hibernate, I extended UserType class to create custom

    type converter, which is responsible for a serialization ofthe Java enum into its database VARCHAR representa-tion and back.

    In OpenJPA, I annotated the gender field with @Externalizer("toString")and @Factorty, as described in section 2.4. Since for @Factory,I did not specify any additional parameter, the construc-tor will be called for obtaining new Gender instance.

    For OpenJPA, I enabled unenhanced persistent classes on run-time using configuration property openjpa.RuntimeUnenhancedClasses.

    Even though the classes should be enhanced automaticallyduring the deployment on the JBoss application server, I wasreceiving an error that they are not. Even though I might haverun compile-time enhancement using Ant or Maven (like Idid in the performance benchmark), I decided to simply allowclasses to be unenhanced in this case.

    3.4 Migration summary

    In this section, I migrated various applications between different JPAimplementations. Two out of three migrations were successful, onewas not. Surprisingly, the unsuccessful one lead to probably the mostinteresting conclusion, because it shows that migrating an applica-tion between JPA providers is not easy if it heavily utilizes the nativeAPI.

    38

  • 7/29/2019 Perbandingan berbagai Provider JPA

    44/58

    4 Automatic migration tool

    Practical part of the thesis is an application providing a support withmigrating existing projects from OpenJPA and EclipseLink to Hiber-nate, I call it JPA Migration and it is written in Scala.

    4.1 The application architecture

    The architecture of the application was designed with emphasis onits extensibility. Migration of a project is divided into migrating in-

    dividual source files using so called processors. They are responsi-ble for locating various vendor specific features and displaying hintshow could such features be migrated to Hibernate1. If there is a directcounterpart in Hibernate, the feature is migrated automatically2.

    For both supported JPA implementations (OpenJPA, Hibernate),there are several processors configured in the application configu-ration. All parsers mix in3 the trait Processor, which defines twoabstract methods:

    appliesFor(filename: String) returns a boolean value in-

    dicating whether the processor should be executed for a filewith a particular filename.

    parse(source: String) receives a file content as a functionargument, analyses it, migrates the constructs it is responsiblefor, and returns a tuple, where the first element is a new mi-grated source4 and the second argument is a list of instancesof MigrationTaskResult, which provides a description of asingle step performed during the migration.

    1. If it is possible to migrate a specific vendor-specific feature directly to the stan-dard API, it will be preferred over migrating to Hibernate.2. Currently, there are automatically migrated only standardized JPA persis-tence.xml properties and some query hints whose semantics is the same in mul-tiple frameworks.3. Mix in a Scala train is kind of an alternative concept to implementing an inter-face in Java.4. When no migration is done, the returned source is the same as the input.

    39

  • 7/29/2019 Perbandingan berbagai Provider JPA

    45/58

    4. AUTOMATIC MIGRATION TOOL

    There are two additional abstract classes PropertiesXmlProcessor

    and ClassProcessor, which both mix in Processor and serve asbase classes of all processors working with Java sources files or XML,respectively. They provide various convenience methods for all theprocessors of the same kind. On figure 4.1 there is the class diagramdescribing all the classes participating in the migration process.

    The migration process itself consists of following steps:

    1. The application starts. It receives four command-line argu-ments:

    the project directory

    an output directory

    the location of a file where migration the report shouldbe written to

    the name of the current JPA provider (eclipselink or open-jpa)

    2. The arguments are validated (e.g. if the project directory ex-ists, if the output directory is writeable, some additional ac-cess right are checked, etc.)

    3. The migration itself begins. The input directory is as a wholecopied to the output destination.

    4. The list of available processors for the particular JPA imple-mentation is loaded from the application configuration.

    5. The output directory is walked recursively and for each file,all processors whose method appliesFor() returns true, aresubsequently executed5; each consecutive processor receivesthe output of the previous processor as an input argument.Implemented this way, the source code is successively migrated

    and the lists of MigrationTaskResult instances (the secondelement of a tuple returned by the parse() method) are con-catenated, forming a complete migration report for a particu-lar file, represented by an instance of class Report.

    5. Their method parse() is executed.

    40

  • 7/29/2019 Perbandingan berbagai Provider JPA

    46/58

    4. AUTOMATIC MIGRATION TOOL

    6. Migrated source code is written back to the source file.

    7. Instances ofReport created during the migration of individ-ual source files are collected and passed as an argument to thetemplating engine Scalate, which is responsible for creatingHTML report using the predefined template.

    4.2 Java source files parsing

    While the parsing of XML configuration files is rather straightfor-ward and only involves quite simple DOM tree manipulation, pars-ing Java source files and their analysis is much more complicated. Itis necessary to obtain an abstract representation of a Java source file an abstract syntax tree (AST). Such AST is then recursively searchedfor occurrences of vendor-specific constructs, such as types, anno-tations or imports. For creating AST representations of Java sourcefiles, I use the library javaparser6.

    In listing 4.1, I demonstrate how Scala pattern matching [18] isused to recursively browse an AST and search for a specific annota-

    tion. The method receives three arguments an instance ofCompilationUnitwhich is an abstract representation of a single source file; an annota-tion to search for and a closure to call for all annotations found. Themethod recursively searches all types (classes or interfaces) and theirmembers (fields, constructors, methods and inner classes) if they aredeclared with a specific annotation. If such annotation is found, theclosure is called, passing the found annotation as an argument. Suchsolution is very flexible the client just passes in an arbitrary closurewhich is guaranteed to be called for all matching annotations found.It is a responsibility of the caller7 to do something useful with it.

    Since the very same approach is used to search for occurrencesof vendor-specific types in an AST, pattern matching and recursivefunctions are of a great use here again. I browse the AST from the

    6. http://code.google.com/p/javaparser/7. The callers in the current architecture are the processors.

    41

    http://code.google.com/p/javaparser/http://code.google.com/p/javaparser/
  • 7/29/2019 Perbandingan berbagai Provider JPA

    47/58

    4. AUTOMATIC MIGRATION TOOL

    top8, pattern match on the class of the current statement and recur-

    sively unwrap simpler statements out of the more complex ones.For example, when parsing an if statement, I recursively parse itscondition, if block and else block. When a vendor-specific type isencountered at any point, the closure passed as an argument to theparsing function is called, passing it the found type as an argument.

    def processAnnotations(unit: CompilationUnit,

    annotation: String,

    closure: (AnnotationExpr => Unit)) {

    if (unit.getTypes != null)

    unit.getTypes.foreach(handleMember)

    def handleMember(element: BodyDeclaration) {

    element match {

    case x: ClassOrInterfaceDeclaration => {

    handleAllowedType()

    x.getMembers.foreach(handleMember)

    }

    case _: FieldDeclaration |

    _: ConstructorDeclaration |

    _: MethodDeclaration => handleAllowedType()

    case _ =>

    }

    def handleAllowedType() {

    if (element.getAnnotations != null)

    element.getAnnotations.foreach(x => if

    (x.getName.getName == annotation)

    closure(x))

    }

    }

    }

    Listing 4.1: Recursively searching the abstract syntax tree for vendor-

    8. It means that the parsing starts with the whole source file, then recurses into allthe types it contains, then to all their fields, methods and constructors which con-tain various language constructs, such as ifs, loops, anonymous classes, returns,etc., down to atomic statements like string literals or null expressions.

    42

  • 7/29/2019 Perbandingan berbagai Provider JPA

    48/58

    4. AUTOMATIC MIGRATION TOOL

    specific annotations using Scala pattern matching

    4.3 Ideas for a further development

    The application is written in a clean functional style, with empha-sis on its extensibility and code clarity. Migration of additional con-structs is just a matter of writing a processor (which is very simpleif one of the abstract classes providing support for manipulating theDOM or browsing an AST is extended) and plugging it into the ap-plication by simply configuring the class name of the processor in

    the config.properties configuration file. The current implementationcontains support for migrating almost all the features described inchapter 2. However, as I noted earlier, both JPA implementationscontain additional features, which were not discussed and the pars-ing of which is currently not implemented. Therefore, a future de-velopment might focus on parsing and migrating additional vendor-specific features, which are not handled in the current implementa-tion.

    Additional problem is that the parser used for creating AST sup-port only Java up to version 5. Therefore, parsing of Java source files

    which contain new language constructs introduced in Java 6 or Java7 (such as the diamond operator or try block with resources), leads toparsing errors. Unfortunately, this is not easy to fix because it wouldrequire the change of the parser and very likely also most of the pro-cessing logic.

    43

  • 7/29/2019 Perbandingan berbagai Provider JPA

    49/58

    4. AUTOMATIC MIGRATION TOOL

    Figure 4.1: Class diagram of the migration application

    44

  • 7/29/2019 Perbandingan berbagai Provider JPA

    50/58

    5 Conclusion

    In the theoretical part of the thesis I was comparing the most popu-lar JPA implementations according to various criteria I selected. Anexpected output from any comparison work is a ranking indicatingwho the winners and the losers are. Unfortunately, create such rank-ing is not possible in case of JPA implementations. All implemen-tation have their strengths and weaknesses and it heavily dependson the needs of the implementer. Hibernate would be the choice forits large community, high-quality documentation, integration withmany other frameworks and the support provided by JBoss. Eclipse-Link, however, is the reference implementation of the JPA standardand its biggest advantage is its great support for stored procedures.And finally OpenJPA contains the most powerful features in the areaof a schema generation and generation of persistence classes out ofexisting database schema. However, as I discovered in chapter 3, ifa project is heavily utilizing native features of any JPA implemen-tation, it is necessary to remember that the migration process fromone provider to another will be difficult and will require significantchanges in the code base.

    Practical part involved creating an application providing support

    for migrating a project from one JPA provider to another. The appli-cation is developed in the Scala programming language and is calledJPA migration. It goes through all the sources contained in the sourcedirectory, searches for vendor-specific features and tries to migratethem automatically either to the standard API or to Hibernate if thereis not any standard alternative. If it is not possible to it automatically,it displays a hint how could the particular vendor-specific feature bemigrated manually, as well as a link to the corresponding chapter inthe documentation.

    45

  • 7/29/2019 Perbandingan berbagai Provider JPA

    51/58

    A Generated database schemas

    A.1 Hibernate

    create table "user" (

    user_id int8 not null,

    enabled boolean,

    username varchar(255) not null unique,

    primary key (user_id)

    )

    create table article (

    article_id int8 not null,

    content varchar(255) not null,

    created timestamp,

    headline varchar(255) not null,

    discussion_id int8 not null,

    primary key (article_id)

    )

    create table articles_tags (article_id int8 not null,

    tag_id int8 not null,

    primary key (article_id, tag_id)

    )

    create table discussion (

    discussion_id int8 not null,

    primary key (discussion_id)

    )

    create table discussions_posts (discussion_id int8 not null,

    post_id int8 not null unique,

    unique (post_id)

    )

    create table post (

    46

  • 7/29/2019 Perbandingan berbagai Provider JPA

    52/58

    A. GENERATED DATABASE SCHEMAS

    post_id int8 not null,

    author varchar(255) not null,

    created timestamp,

    text varchar(255) not null,

    title varchar(255) not null,

    primary key (post_id)

    )

    create table tag (

    tag_id int8 not null,

    name varchar(255) not null unique,

    primary key (tag_id)

    )

    create table users_articles (

    user_id int8 not null,

    article_id int8 not null,

    primary key (user_id, article_id)

    )

    create table users_authorities (

    user_id int8 not null,

    name varchar(255) not null,

    primary key (user_id, name)

    )

    alter table article

    add constraint FKD458CCF6386589CA

    foreign key (discussion_id)

    references discussion

    alter table articles_tags

    add constraint FK487AF8DBDF6FF6EA

    foreign key (article_id)

    references article

    alter table articles_tags

    add constraint FK487AF8DBBBDB3C6A

    foreign key (tag_id)

    references tag

    47

  • 7/29/2019 Perbandingan berbagai Provider JPA

    53/58

    A. GENERATED DATABASE SCHEMAS

    alter table discussions_posts

    add constraint FKA16447DF386589CA

    foreign key (discussion_id)

    references discussion

    alter table discussions_posts

    add constraint FKA16447DF48822CA

    foreign key (post_id)

    references post

    alter table users_articles

    add constraint FK2F4ABE94DF6FF6EA

    foreign key (article_id)

    references article

    alter table users_articles

    add constraint FK2F4ABE941316CEEA

    foreign key (user_id)

    references "user"

    alter table users_authorities

    add constraint FK6555336A1316CEEA

    foreign key (user_id)

    references "user"

    create sequence sample_sequence

    Listing A.1: Hibernate-generated sample database schema

    A.2 OpenJPA

    CREATE SEQUENCE sample_sequence START WITH 1 CACHE 50;

    CREATE TABLE "user" (user_id BIGINT NOT NULL, enabled

    BOOL, username VARCHAR(255) NOT NULL, PRIMARY KEY

    (user_id), CONSTRAINT U_USER_USERNAME UNIQUE

    (username));

    48

  • 7/29/2019 Perbandingan berbagai Provider JPA

    54/58

    A. GENERATED DATABASE SCHEMAS

    CREATE TABLE article (article_id BIGINT NOT NULL,

    content VARCHAR(255) NOT NULL, created TIMESTAMP,

    headline VARCHAR(255) NOT NULL, discussion_id

    BIGINT NOT NULL, PRIMARY KEY (article_id));

    CREATE TABLE articles_tags (article_id BIGINT, tag_id

    BIGINT);

    CREATE TABLE discussion (discussion_id BIGINT NOT

    NULL, PRIMARY KEY (discussion_id));

    CREATE TABLE discussions_posts (discussion_id BIGINT

    NOT NULL, post_id BIGINT NOT NULL, CONSTRAINT

    U_DSCSSTS_POST_ID UNIQUE (post_id));

    CREATE TABLE post (post_id BIGINT NOT NULL, author

    VARCHAR(255) NOT NULL, created TIMESTAMP, text

    VARCHAR(255) NOT NULL, title VARCHAR(255) NOT

    NULL, PRIMARY KEY (post_id));

    CREATE TABLE tag (tag_id BIGINT NOT NULL, name

    VARCHAR(255) NOT NULL, PRIMARY KEY (tag_id),

    CONSTRAINT U_TAG_NAME UNIQUE (name));

    CREATE TABLE users_articles (user_id BIGINT,

    article_id BIGINT);

    CREATE TABLE users_authorities (user_id BIGINT, name

    VARCHAR(255) NOT NULL);

    CREATE INDEX I_ARTICLE_DISCUSSION ON article

    (discussion_id);

    CREATE INDEX I_RTCLTGS_ARTICLE_ID ON articles_tags

    (article_id);

    CREATE INDEX I_RTCLTGS_ELEMENT ON articles_tags

    (tag_id);

    CREATE INDEX I_DSCSSTS_DISCUSSION_ID ON

    discussions_posts (discussion_id);

    CREATE INDEX I_DSCSSTS_ELEMENT ON discussions_posts

    (post_id);

    CREATE INDEX I_SRS_CLS_ELEMENT ON users_articles

    (article_id);

    CREATE INDEX I_SRS_CLS_USER_ID ON users_articles

    (user_id);

    CREATE INDEX I_SRS_RTS_USER_ID ON users_authorities

    (user_id);

    Listing A.2: OpenJPA-generated sample database schema

    49

  • 7/29/2019 Perbandingan berbagai Provider JPA

    55/58

    A. GENERATED DATABASE SCHEMAS

    A.3 EclipseLink

    CREATE TABLE article (article_id BIGINT NOT NULL,

    content VARCHAR(255) NOT NULL, created TIMESTAMP,

    headline VARCHAR(255) NOT NULL, discussion_id

    BIGINT NOT NULL, PRIMARY KEY (article_id))

    CREATE TABLE discussion (discussion_id BIGINT NOT

    NULL, PRIMARY KEY (discussion_id))

    CREATE TABLE post (post_id BIGINT NOT NULL, author

    VARCHAR(255) NOT NULL, created TIMESTAMP, textVARCHAR(255) NOT NULL, title VARCHAR(255) NOT

    NULL, PRIMARY KEY (post_id))

    CREATE TABLE tag (tag_id BIGINT NOT NULL, name

    VARCHAR(255) NOT NULL UNIQUE, PRIMARY KEY (tag_id))

    CREATE TABLE "user" (user_id BIGINT NOT NULL, enabled

    BOOLEAN, username VARCHAR(255) NOT NULL UNIQUE,

    PRIMARY KEY (user_id))

    CREATE TABLE users_articles (article_id BIGINT NOT

    NULL, user_id BIGINT NOT NULL, PRIMARY KEY

    (article_id, user_id))

    CREATE TABLE articles_tags (article_id BIGINT NOTNULL, tag_id BIGINT NOT NULL, PRIMARY KEY

    (article_id, tag_id))

    CREATE TABLE discussions_posts (discussion_id BIGINT

    NOT NULL, post_id BIGINT NOT NULL UNIQUE, PRIMARY

    KEY (discussion_id, post_id))

    CREATE TABLE users_authorities (user_id BIGINT, name

    VARCHAR(255) NOT NULL)

    ALTER TABLE article ADD CONSTRAINT

    FK_article_discussion_id FOREIGN KEY

    (discussion_id) REFERENCES discussion

    (discussion_id)ALTER TABLE users_articles ADD CONSTRAINT

    FK_users_articles_article_id FOREIGN KEY

    (article_id) REFERENCES article (article_id)

    ALTER TABLE users_articles ADD CONSTRAINT

    FK_users_articles_user_id FOREIGN KEY (user_id)

    REFERENCES "user" (user_id)

    50

  • 7/29/2019 Perbandingan berbagai Provider JPA

    56/58

    A. GENERATED DATABASE SCHEMAS

    ALTER TABLE articles_tags ADD CONSTRAINT

    FK_articles_tags_tag_id FOREIGN KEY (tag_id)

    REFERENCES tag (tag_id)

    ALTER TABLE articles_tags ADD CONSTRAINT

    FK_articles_tags_arti