Java persistence

S

Shiladitya

Hi,
I am new to Java and need a simple, easy to use library to map Java
classes with MySQL tables. I came across Hibernate and Google persist.
Can you suggest pros and cons of these or suggest some other better
ORM ?

TIA
Shiladitya
 
L

Lew

Hi,
I am new to Java and need a simple, easy to use library to map Java
classes with MySQL tables. I came across Hibernate and Google persist.
Can you suggest pros and cons of these or suggest some other better
ORM ?

Similar to Hibernate are the Java Persistence API (JPA) implementations
EclipseLink and Apache OpenJPA. They're all three robust and quite useful.
Make sure if you do use Hibernate that you stick with the JPA-compliant part
of it.
 
T

Tom Anderson

I'd never even heard of Google Persist. Here we go:

http://code.google.com/p/persist/

It seems its goal is to be an as-simple-as-possible ORM. Of course,
eliminate the complexity of Hibernate-style ORMs means eliminating some of
their features: notably missing, from what i can see, are relationships
between objects, in that persistent objects can only have fields of simple
types (primitives, strings, and so on).
Similar to Hibernate are the Java Persistence API (JPA) implementations
EclipseLink and Apache OpenJPA. They're all three robust and quite
useful. Make sure if you do use Hibernate that you stick with the
JPA-compliant part of it.

Good advice. I'm using OpenJPA at the moment and, once i realised what i
was doing wrong with the schema generator, it's an absolute doddle to use.
Classes looks like (and this is standard JPA; this will be identical with
Hibernate, EclipseLink, or any other JPA provider):

@Entity
public class Customer {
@Id
private int customerNumber;
private String name;
@OneToMany(mappedBy="customer")
private List<Order> orders;
// constructor, methods, etc
}

@Entity
public class Order {
@Id
private orderNumber;
@ManyToOne
private Customer customer;
// constructor, methods, etc
}

You compile that as normal.

You put a persistence.xml file in the classpath root with these contents
(again, this is standard JPA):

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="example" transaction-type="RESOURCE_LOCAL" />
</persistence>

You then set up properties describing the database conenction; i do this
as an environment variable in a shell script, because i think it's runtime
configuration rather than part of the code, but you can also put this in
the persistence.xml file. Mine look like:

DB_ARGS="-Dopenjpa.ConnectionDriverName=$DB_DRIVER -Dopenjpa.ConnectionURL=$DB_URL -Dopenjpa.ConnectionUserName=$DB_USER -Dopenjpa.ConnectionPassword=$DB_PASS"

That's not standard JPA; i think JPA 2.0 defines standard property names
for the database connection details, but OpenJPA doesn't support them yet.

You then generate SQL for the necessary tables like this (having defined
the classpath variables appropriately):

java -cp "$PROJECT_CLASSPATH:$OPENJPA_CLASSPATH:$DB_CLASSPATH" $DB_ARGS org.apache.openjpa.jdbc.meta.MappingTool -schemaAction build -sql schema.sql

You then run that schema.sql against your database. You can use the
mapping tool to set up the tables directly, but i prefer to make SQL and
then run that, because i have a record of exactly what gets done. This bit
is entirely OpenJPA-specific, i'm afraid. I think the resulting SQL files
would work with any JPA provider, though - i think the default mapping is
standardised.

You then write code to manipulate the objects like this (again, this is
standard JPA):

EntityManagerFactory emf = Persistence.createEntityManagerFactory("example"); // name matches the one in persistence.xml
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
Customer c = new Customer(100, "Harry Brown");
Order o = new Order(83479);
c.addOrder(o);
em.persist(c);
tx.commit();
}
finally {
if (tx.isActive()) {
tx.rollback();
}
em.close();
}

You compile that as normal, and run it with:

java -cp "$PROJECT_CLASSPATH:$OPENJPA_CLASSPATH:$DB_CLASSPATH" $DB_ARGS MainClass

That's it.

Now, there are three things i really should have done but didn't, because
they in fact aren't truly necessary.

The first was to give my classes no-args constructors. The JPA spec
requires that entity classes have public or protected no-args
constructors. As it happens, the OpenJPA entity enhancer adds these if
they're needed. For portability and correctness, you should add them
explicitly.

The second was to list the entity classes in the persistence.xml. I'm not
sure the spec requires this, but i think it's a good idea even if it
doesn't - OpenJPA warns that i haven't done it, but deals with it. I have
a step in my build script which adds them automatically, so there's no
manual work involved in this for me.

The third is to enhance my classes manually. For OpenJPA, class files need
to be modified before they are loaded to allow transparent persistence.
You can do this with a command-line tool at build time, but if you don't,
OpenJPA can usually load an agent at runtime which will do it on the fly.
It's safer to do it at build time, though. Again, i have a line in my
script which does this, so there's no manual work.

So, even doing it properly, JPA is pretty simple.

tom
 
S

Shiladitya

I'd never even heard of Google Persist. Here we go:

http://code.google.com/p/persist/

It seems its goal is to be an as-simple-as-possible ORM. Of course,
eliminate the complexity of Hibernate-style ORMs means eliminating some of
their features: notably missing, from what i can see, are relationships
between objects, in that persistent objects can only have fields of simple
types (primitives, strings, and so on).



Good advice. I'm using OpenJPA at the moment and, once i realised what i
was doing wrong with the schema generator, it's an absolute doddle to use..
Classes looks like (and this is standard JPA; this will be identical with
Hibernate, EclipseLink, or any other JPA provider):

@Entity
public class Customer {
        @Id
        private int customerNumber;
        private String name;
        @OneToMany(mappedBy="customer")
        private List<Order> orders;
        // constructor, methods, etc

}

@Entity
public class Order {
        @Id
        private orderNumber;
        @ManyToOne
        private Customer customer;
        // constructor, methods, etc

}

You compile that as normal.

You put a persistence.xml file in the classpath root with these contents
(again, this is standard JPA):

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
     <persistence-unit name="example" transaction-type="RESOURCE_LOCAL" />
</persistence>

You then set up properties describing the database conenction; i do this
as an environment variable in a shell script, because i think it's runtime
configuration rather than part of the code, but you can also put this in
the persistence.xml file. Mine look like:

DB_ARGS="-Dopenjpa.ConnectionDriverName=$DB_DRIVER -Dopenjpa.ConnectionURL=$DB_URL -Dopenjpa.ConnectionUserName=$DB_USER -Dopenjpa.ConnectionPassword=$DB_PASS"

That's not standard JPA; i think JPA 2.0 defines standard property names
for the database connection details, but OpenJPA doesn't support them yet..

You then generate SQL for the necessary tables like this (having defined
the classpath variables appropriately):

java -cp "$PROJECT_CLASSPATH:$OPENJPA_CLASSPATH:$DB_CLASSPATH" $DB_ARGS org.apache.openjpa.jdbc.meta.MappingTool -schemaAction build -sql schema.sql

You then run that schema.sql against your database. You can use the
mapping tool to set up the tables directly, but i prefer to make SQL and
then run that, because i have a record of exactly what gets done. This bit
is entirely OpenJPA-specific, i'm afraid. I think the resulting SQL files
would work with any JPA provider, though - i think the default mapping is
standardised.

You then write code to manipulate the objects like this (again, this is
standard JPA):

EntityManagerFactory emf = Persistence.createEntityManagerFactory("example"); // name matches the one in persistence.xml
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
        tx.begin();
        Customer c = new Customer(100, "Harry Brown");
        Order o = new Order(83479);
        c.addOrder(o);
        em.persist(c);
        tx.commit();}

finally {
        if (tx.isActive()) {
                tx.rollback();
        }
        em.close();

}

You compile that as normal, and run it with:

java -cp "$PROJECT_CLASSPATH:$OPENJPA_CLASSPATH:$DB_CLASSPATH" $DB_ARGS MainClass

That's it.

Now, there are three things i really should have done but didn't, because
they in fact aren't truly necessary.

The first was to give my classes no-args constructors. The JPA spec
requires that entity classes have public or protected no-args
constructors. As it happens, the OpenJPA entity enhancer adds these if
they're needed. For portability and correctness, you should add them
explicitly.

The second was to list the entity classes in the persistence.xml. I'm not
sure the spec requires this, but i think it's a good idea even if it
doesn't - OpenJPA warns that i haven't done it, but deals with it. I have
a step in my build script which adds them automatically, so there's no
manual work involved in this for me.

The third is to enhance my classes manually. For OpenJPA, class files need
to be modified before they are loaded to allow transparent persistence.
You can do this with a command-line tool at build time, but if you don't,
OpenJPA can usually load an agent at runtime which will do it on the fly.
It's safer to do it at build time, though. Again, i have a line in my
script which does this, so there's no manual work.

So, even doing it properly, JPA is pretty simple.

tom

Thanks for the suggestions Lew, and code snippets Tom. I think I will
use OpenJPA and see how it goes.
 
R

Roedy Green

I am new to Java and need a simple, easy to use library to map Java
classes with MySQL tables. I came across Hibernate and Google persist.
Can you suggest pros and cons of these or suggest some other better
ORM ?

If you are new to Java, you might avoid an ORM for now. Then when you
use Hibernate or similar, you will have a better idea of what is going
on under the covers which should help in training Hibernate to jump
through hoops.
 
A

Arne Vajhøj

Similar to Hibernate are the Java Persistence API (JPA) implementations
EclipseLink and Apache OpenJPA. They're all three robust and quite
useful. Make sure if you do use Hibernate that you stick with the
JPA-compliant part of it.

I consider that very good advice.

Unfortunately it is not widely followed.

Arne
 
A

Arved Sandstrom

Arne said:
I consider that very good advice.

Unfortunately it is not widely followed.

Arne

One reason it hasn't been widely followed is that with JPA 1.0 there were
important and interesting things that you couldn't do with JPA, but
Hibernate or EclipseLink (or presumably OpenJPA) did supply useful APIs to
do them. There should be considerably fewer reasons to dive into native API
land when using JPA 2.0 implementations.

AHS
 
A

Arne Vajhøj

One reason it hasn't been widely followed is that with JPA 1.0 there were
important and interesting things that you couldn't do with JPA, but
Hibernate or EclipseLink (or presumably OpenJPA) did supply useful APIs to
do them. There should be considerably fewer reasons to dive into native API
land when using JPA 2.0 implementations.

My guess is that even for JPA 1.0 it was more laziness/ignorance
than need for specific features.

Arne
 
A

Arved Sandstrom

Arne said:
My guess is that even for JPA 1.0 it was more laziness/ignorance
than need for specific features.

Arne

In some cases ego. Based on code I've had to maintain some programmers never
saw an API but that they had to figure out a way to include a use of it.

AHS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top