This is how I configure JPA in Spring.
... <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"> </bean> <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property> <property name="url" value="jdbc:mysql://localhost:3306/test"> </property> <property name="username" value="root"> </property> <property name="password" value="root"> </property> </bean> <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> <property name="jpaVendorAdapter" ref="jpaVendorAdapter"> </property> <property name="dataSource" ref="dataSource"> </property> <property name="packagesToScan" value="org.huahsin"> </property> </bean> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" id="jpaVendorAdapter"> <property name="databasePlatform" value="org.hibernate.dialect.MySQLInnoDBDialect"> </property> <property name="showSql" value="true"> </property> </bean>The primary object in this configuration was the LocalContainerEntityManagerFactoryBean. According to the documentation, this is the most powerful way to set up a shared JPA EntityManagerFactory in Spring application context. I take 3 parameters in this configuration:
- dataSource - the bean that establish connection to database.
- jpaVendorAdapter - optional parameters in persistence.xml.
- packagesToScan - the packages where the entities is reside.
@Repository
public class UserDao implements IUserDao {
@PersistenceUnit
private EntityManagerFactory emf;
public User findByUsername(String username) {
List<user> l = null;
try {
l = (List<user>) emf.createEntityManager().createQuery("from User").getResultList();
// verify on the list of users
for( User u : l ) {
System.out.println(u.getUsername());
}
return null; // simply return NULL for testing purpose
}
finally {
emf.close();
}
}
}
The second option is to obtain an instance of EntityManager through @PersistenceContext injection.@Repository
public class UserDao implements IUserDao {
@PersistenceContext
private EntityManager em;
public User findByUsername(String username) {
List<User> l = null;
try {
l = (List<User>) em.createQuery("from User").getResultList();
// verify on the list of users
for( User u : l ) {
System.out.println(u.getUsername());
}
return null; // simply return NULL for testing purpose
}
finally {
emf.close();
}
}
}
Do not mess up with the injection. If I accidentally do this on EntityManagerFactory like this:@PersistenceContext
private EntityManagerFactory emf;
This error would be seen when the bean is trigger during run-time:
Caused by: java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManagerFactory] is incompatible with resource type [javax.persistence.EntityManager] at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.checkResourceType(InjectionMetadata.java:134) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.<init>(PersistenceAnnotationBeanPostProcessor.java:620) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:381) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:322) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:830) ... 27 moreSame to EntityManager, if I mistakenly do this:
@PersistenceUnit
private EntityManager em;
This will be the result during the run-time:
Caused by: java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManager] is incompatible with resource type [javax.persistence.EntityManagerFactory] at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.checkResourceType(InjectionMetadata.java:134) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.There is a nice comment on this error why this shouldn't be done appear on this question in stackoverflow.com. The user claim that(PersistenceAnnotationBeanPostProcessor.java:620) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:381) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:322) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:830) ... 27 more
An entity manager can only be injected in classes running inside a transaction. In other words, it can only be injected in a EJB. Other classe must use an EntityManagerFactory to create and destroy an EntityManager. - Andre Rodrigues

No comments:
Post a Comment