Hibernate with JPA Annotations and Guice
In this tutorial, I use the H2 database, which you can utilize by downloading the jar or you can replace with your own DB.
First off, you need to create a persistence.xml in a folder named META-INF at the root of your classpath. For example, if you’re using Maven you can create src/main/java/META-INF/persistence.xml. It lists all the classes you want Hibernate to persist and any other Hibernate properties you might want to specify. I also define Hibernate properties later on in the tutorial when creating the EntityManagerFactory.
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="db-manager">
<class>com.benmccann.db.ExamplePersistedClass</class>
<properties>
<!-- Disable the second-level cache -->
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<!-- Default is false for backwards compatibility. Should be used on all new projects -->
<property name="hibernate.id.new_generator_mappings" value="true"/>
</properties>
</persistence-unit>
</persistence>
We listed the class com.benmccann.db.ExamplePersistedClass as being the only persisted class, so now we’ll go ahead and create it. Note that you need a no-argument constructor. Fields in your bean will be persisted unless annotated with @Transient. More info about persisted classes is available in the Hibernate documentation.
package com.benmccann.db;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class ExamplePersistedClass {
@Id
@GeneratedValue
private Long id;
private String otherField;
public ExamplePersistedClass() {}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setOtherField(String otherField) {
this.otherField = otherField;
}
public String getOtherField() {
return otherField;
}
}
And we’ll create a DAO for it:
package com.benmccann.db;
import javax.persistence.EntityManager;
public class ExamplePersistedClassDao {
protected EntityManager entityManager;
@Inject
public ExamplePersistedClassDao(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void saveInNewTransaction(ExamplePersistedClass object) {
entityManager.getTransaction().begin();
save(object);
entityManager.getTransaction().commit();
}
public void save(ExamplePersistedClass object) {
entityManager.persist(object);
}
public ExamplePersistedClass getByOtherField(String otherField) {
return (ExamplePersistedClass) entityManager
.createQuery("select e from ExamplePersistedClass e where e.otherField=:otherField")
.setParameter("otherField", otherField)
.getSingleResult();
}
}
And finally, we’ll create a Guice module to define the injection. Note that EntityManagerFactory is thread-safe while EntityManager is not. I use ThreadLocal storage here in order to have one entity manager per thread. When creating the EntityManagerFactory notice that I use the same “db-manager” string that is defined in the persistence.xml file. Also, I defined most of my Hibernate properties here rather than in the persistence.xml file to demonstrate how you can alter the values of these properties. For example, when writing tests it could be very helpful to override the connection string to point to a local test database.
package com.benmccann.db;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
/**
* @author Ben McCann (benmccann.com)
*/
public class DbModule extends AbstractModule {
private static final ThreadLocal<EntityManager> ENTITY_MANAGER_CACHE
= new ThreadLocal<EntityManager>();
public void configure() {
}
@Provides @Singleton
public EntityManagerFactory provideEntityManagerFactory() {
Map<String, String> properties = new HashMap<String, String>();
properties.put("hibernate.connection.driver_class", "org.h2.Driver");
properties.put("hibernate.connection.url", "jdbc:h2:test");
properties.put("hibernate.connection.username", "sa");
properties.put("hibernate.connection.password", "");
properties.put("hibernate.connection.pool_size", "1");
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.hbm2ddl.auto", "create");
return Persistence.createEntityManagerFactory("db-manager", properties);
}
@Provides
public EntityManager provideEntityManager(EntityManagerFactory entityManagerFactory) {
EntityManager entityManager = ENTITY_MANAGER_CACHE.get();
if (entityManager == null) {
ENTITY_MANAGER_CACHE.set(entityManager = entityManagerFactory.createEntityManager());
}
return entityManager;
}
}
Now we can run our code:
package com.benmccann.db;
import java.sql.SQLException;
import java.util.Date;
import org.junit.Assert;
import org.junit.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.benmccann.db.DbModule;
import com.benmccann.db.ExamplePersistedClass;
import com.benmccann.db.ExamplePersistedClassDao;
public class H2DBTest {
@Test
public void testDb() throws SQLException {
Injector injector = Guice.createInjector(new DbModule());
ExamplePersistedClassDao examplePersistedClassDao = injector.getInstance(ExamplePersistedClassDao.class);
ExamplePersistedClass example = new ExamplePersistedClass();
example.setOtherField("hello world");
examplePersistedClassDao .saveInNewTransaction(quote);
ExamplePersistedClass retrieved = examplePersistedClassDao.getByOtherField("hello world");
Assert.assertEquals(example.getId(), retrieved.getId());
Assert.assertEquals(example.getOtherField(), retrieved.getOtherField());
}
}
thanks, this was useful for me
This is the best quickstart for JPA i’ve ever seen, which get rids of spring framework.
I hereby add the missing dependencies, it maybe not easy to find them out for Maven users,
javax.persistence
persistence-api
1.0
com.google.inject
guice
3.0-rc2
com.h2database
h2
1.3.149
org.hibernate
hibernate-core
3.3.2.GA
I’m getting
Error in custom provider, javax.persistence.PersistenceException: No Persistence provider for EntityManager named db-manager
When trying this in intellij Community Edition and using Maven (and the dependencies mentioned by Lenik
I assume its not finding my persistence.xml, but I’m at a loss as to where to put it. (The location you suggest doesn’t seem to work.
Turns out you need further dependancies
org.hibernate
hibernate-entitymanager
3.3.2.GA
org.slf4j
slf4j-simple
1.6.1
Also a runtime dependency on
javax.transaction:jta:1.1
if you use Java SE
This is an excellent summary.
However, you could omit the section of the persistence.xml, in my experience.
Hi All,
I was also getting “No Persistence provider for EntityManager named db-manager” whilst running test.
Please make sure that you have copied persistance.xml in “src/test/resources/META-INF/”.
Cheers,
Rajesh
Nice article, thanks a lot.
It is all I need.
But the code is hard to read, please use a syntax highlighting plugin !
That was EXACTLY what I was looking for.
Really nice post.
Thanks a lot.
Very cool and dense approach! Thanks a lot for sharing!
Best regards
Is this approach more desired vs warp? http://www.wideplay.com/guicewebextensions2
It seems that warp is not being maintained
Hi,I am trying to run hslqdb in standalone mode. Here is what I have done :1. In hibernate.cfg.xml I have :a. property name=”connection.driver_class”>org.hslqdb.jdbcDriver /property>b. property name=”connection.url”>jdbc.hslqdb.file:data/db/mydb /property>2. In Java code :Class.forName(org.hslqdb.jdbcDriver);Connection connection = DriverManager.getConnection(jdbc.hslqdb.file:data/db/mydb);Now when I am using it from netbeans i.e running it from within netbeans – it runs fine.But when I use the jar file generated by netbeans – the application creates new database files and as such cannot find the files and stuff.———————————Here is my folder structure :src -… -… -…lib -… -…data – db – mydbThe generated jar doesn’t copy the data folder to dist folder.——————————Even if I put data folder inside src – it doesn’t work (but this time myApplication.jar folder does have the data folder inside it)——————————Any help would be much appreciated…
Hmm… The logic isn’t really production ready – at least if used in a web app.
Hibernates connection pool is very basic and is not production ready – the recommendation is to use a datasource pool such as c3p0.
EntityManager shouldn’t be reused – it is intended to be created per transaction/request. There is a good chance of polluting subsequent requests.
There is also no transaction rollback if something goes wrong.
An interesting approach – but it would be much safer for webapps to use Guices own Persist extension module for managing the lifecycle of EntityMananger instances and transactions.
Cheers
Getting a MissingImplementation… this is so frustrating, this is a 5 minutes JOB in SpringBoot and becomes 2 hours in GUICE.
What I am missing? I did exactly as in your code.
1) [Guice/MissingImplementation]: No implementation for EntityManager was bound.
Requested by:
1 : UserProfileDaoInMemory.(UserProfileDaoInMemory.java:21)
\_ for 1st parameter
at ProfileModule.configure(ProfileModule.java:14)
\_ installed by: Elements$ElementsAsModule -> UserProfileApiModule -> ProfileModule
Learn more:
https://github.com/google/guice/wiki/MISSING_IMPLEMENTATION
1 error
======================
Full classname legend:
======================
Elements$ElementsAsModule: “com.google.inject.spi.Elements$ElementsAsModule”
EntityManager: “javax.persistence.EntityManager”