hello folks
I know, I was out of the date for a long time and may will be, because I'm really busy okay it doesn't matter
I'm still playing with JPA and today we want talk about OpenJPA
okay, OpenJPA is a JPA provider, and if we want use it we should know about something
at the first lets talk about difference
1: Persistence.xml
look at this persist configuration file
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="JPA" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <!--[0]-->
<class>_PBeans.authors</class> <!--[1]-->
<class>_PBeans.books</class>
<class>_PBeans.booksAuthors</class>
<class>_PBeans.comments</class>
<class>_PBeans.users</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties> <!--[2]-->
<property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3309/mylib"/>
<property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
<property name="openjpa.ConnectionUserName" value="test"/>
<property name="openjpa.ConnectionPassword" value="test"/>
</properties>
</persistence-unit>
</persistence>
in the above code
[0]: "org.apache.openjpa.persistence.PersistenceProviderImpl" is OpenJPA provider, don't leave it blank
[1]: add the related Entity classes
[2]:set the connection properties
NOTE: don't forget, don't use JNDI when you are using OpenJPA, just set the Data source attributes with properties tag
okay, there isn't any difference in Entity Beans
for example following Entity bean will okay
package _PBeans;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@NamedQuery(name="allBooks",query="select b from books b where b.name like :sk")
@Entity
@Table(name="books")
public class books implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private double price;
@OneToMany(mappedBy="book")
private List<comments> comments;
public void setComments(List<comments> comments){this.comments=comments;}
public List<comments> getComments(){return this.comments;}
@ManyToMany
@JoinTable(name="booksauthors",joinColumns=@JoinColumn(name="bookId",referencedColumnName="id"),inverseJoinColumns=@JoinColumn(name="autId",referencedColumnName="id"))
private List<authors> authors;
public void setAuthors(List<authors> authors){this.authors=authors;}
public List<authors> getAuthors(){return this.authors;}
public void setId(int id){this.id=id;}
public int getId(){return this.id;}
public void setname(String name){this.name=name;}
public String getName(){return this.name;}
public void setPrice(double price){this.price=price;}
public double getPrice(){return this.price;}
}
well, the above Entity beans can used in both of OpenJPA and EclipseLink (for example) or TopLink
okay, buts there is some difference when we are using EntityManagerFactory
so what's the difference?
for example look at this method(a managed bean's method), It will work with Hibernate JPA provider, but won't with OpenJPA
...
@PersistenceUnit(unitName="JPA") //[0]
private EntityManagerFactory EMF;
...
public void getIt(ActionEvent act){
EntityManager EM=EMF.createEntityManager(); //[1]
try{
this.thisBook=EM.find(_PBeans.books.class, this.value);
}catch(Exception e){}
finally{EM.close();}
}
in above code,
[0]: with @persistenceUnit annotation you will create an EntityManagerFactory instance and it really done with Hibernate JPA or EclipsLink
NOTE:with OpenJPA don't use @PersistenceUnit annotation, it will return null at [1]
and the solution,
for creating EntityManagerFactory with OpenJPA we should create it with 'Persistence' class as this
...
private EntityManagerFactory EMF=Persistence.createEntityManagerFactory("JPA", System.getProperties()); //[0]
...
public void getIt(ActionEvent act){
EntityManager EM=EMF.createEntityManager(); //[1]
try{
this.thisBook=EM.find(_PBeans.books.class, this.value);
}catch(Exception e){}
finally{EM.close();}
}
in above code, we didn't use any annotation, and it's not necessary for OpenJPA, for having a EntityManagerFactory we should create it as bold line
NOTE: it won't work with another Providers
Suggestions
there are many cool thing in OpenJPA provider, when you download it from Apache
for example
using OpenJPAEntityManager instead of EntityManager
'OpenJPAEntityManager' has extra futures, such as
removeAll(Collection guys)
persistAll(Collection guys)
and...many more
if you remember we create 'EntityManager' instance from a static method of 'EntityManagerFactory', so it's same for 'OpenJPAEntityManager', but for having a 'OpenJPAEntityManager' we need an 'OpenJPAEntityManagerFactory'
okay look at this example(a managed bean's method)
...
private EntityManagerFactory EMf=Persistence.createEntityManagerFactory("JPA", System.getProperties()); //[0]
private OpenJPAEntityManagerFactory EMF=OpenJPAPersistence.cast(EMf);//[1]
...
public void setBook(ActionEvent act){OpenJPAEntityManager EM=EMF.createEntityManager(); //[2]
if(!this.access()){throw new FacesException("access is denied");} //[*0]
try{
this.book=EM.find(_PBeans.books.class, this.id);
}catch(Exception e){this.mess("an Error occured details: "+e);} //[*0]
finally{EM.close();}
}
...
as you see, we create 'EntityManagerFactory' then cast it to 'OpenJPAEntityManagerFactory'
[0]:at the first create 'EntityManagerFactory' with out any Annotation (like @PersistenceUnit)
[1]:for casting 'EntityManagerFactory' to 'OpenJPAEntityManagerFactory' use 'OpenJPAPersistence' class, it has a static method (cast()) for casting
[2]:and create 'EntityManager'
[*0]s: access() and mess() methods omitted in the code
NOTE: very seldom web application throws nullPointException while it at [2] line, I don't know exactly why! it cause the 'EntityManagerFactory', as I said may it happen very a few times, so for prevent this exception I declare 'EntityManagerFactory' as this way and it doesn't throw any exception yet
Persistence p=new Persistence();
@SuppressWarnings("static-access")
private EntityManagerFactory EMF=p.createEntityManagerFactory("JPA",System.getProperties());
private OpenJPAEntityManagerFactory EMFP=OpenJPAPersistence.cast(EMF);
okay lets play with them more
for example imagine this transaction:
'remove all comments that leaved by User X'
code A:(without OpenJPA)
...
@PersistenceUnit(unitName="JPA")
private EntityManagerFactory EMF;//[0]
...
public void setBook(ActionEvent act){EntityManager EM=EMF.createEntityManager(); //[1]
try{
_PBeans.books book=EM.find(_PBeans.books.class, this.id);
Collection<_PBeans.comments> coms=book.getComments();
EM.getTransaction().begin();
for(_PBeans.comments com:coms) //[2]
{EM.remove(com);} //[3]
EM.getTransaction().commit();
}catch(Exception e){this.mess("an Error occured details: "+e);} //[*0]
finally{EM.close();}
}
...
okay in above code
[0]:creating 'EntityManagerFactory' with @PersistenceUnit annotation
[1]:creating 'EntityManager'
[2]:after finding the wanted user, in a for loop remove each comment
[*0]: omitted method (mess())
but with OpenJPAEntityManager we don't need for loop, because OpenJPAEntityManager has a method for removing a collection of Entity guys this is removeAll(Collection)
so the above code will be like this
...
private EntityManagerFactory EMf=Persistence.createEntityManagerFactory("JPA", System.getProperties()); //[0]
private OpenJPAEntityManagerFactory EMF=OpenJPAPersistence.cast(EMf);//[1]
...
public void setBook(ActionEvent act){OpenJPAEntityManager EM=EMF.createEntityManager(); //[1]
try{
_PBeans.books book=EM.find(_PBeans.books.class, this.id);
EM.getTransaction().begin();
{EM.removeAll(book.getComments());} //[3]
EM.getTransaction().commit();
}catch(Exception e){this.mess("an Error occured details: "+e);} //[*0]
finally{EM.close();}
}
...
as you see with OpenJPAEntityManager we can do things easily
another example(just OpenJPA)
Imagine this transactions
'adding 10 sequential book(book1,book2,...)'
so we can create the books in a for loop and add them to a Collection, then with persistAll(Collection) persist all
another cool method are 'commitAndResume()' and 'rollbackAndResume()'
for example you want begin and commit a transaction and start another transaction, by default we should begin() a transaction and commit() it, and begin() is again
so commitAndResume() method means commit and begin and also about roolbackAndCommit()
setSavePoint() method is one of the cool methods
you can save point your transaction, it will be really helpful for rollback
for example set a point before you commit it, may you want check a condition and it should rollback
save a save point with 'setSavePoint(String savePointName)' and you can back to the point(roolback) with rollbackToSavepoint(String savePointName)
also OpenJPA has more than these guys, but this article just for a abstract of OpenJPA
hope were helpful for you