Spring data JPA java.lang.IllegalArgumentException: Not an entity - spring

I have created spring data JPA sample project. I used eclips for this. There are two projects, one is domain object project which has only annotated entity classes. Other project is actual spring data jpa project and it has a dependency for the project one. Actually it gets domain project entity classes via maven dependency.
Project 1 : hrm-domain
Entity class :
package com.hrm.ws.data.domain;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
#Entity(name = "Employee")
#Table(name = "employee")
#Inheritance(strategy = InheritanceType.JOINED)
public class Employee {
protected long id;
protected String firstName;
protected String lastName;
/**
* Gets the value of the id property.
*
*/
#Id
#Column(name = "id", scale = 0)
#GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
Project 2 : hrm-ws-service
persistance-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<jpa:repositories base-package="com.hrm.ws.data.repository" />
<bean id="employeeDao" class="com.hrm.ws.data.repository.EmployeeRepositoryImpl"/>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="${jdbc.generateDdl}" />
<property name="showSql" value="${jdbc.showSql}"/>
</bean>
</property>
<property name="persistenceUnitName" value="jpa.sample" />
</bean>
</beans>
So the setup for my packages is as follows:
src/main/java - contains the spring repository
src/main/resources - contains application context
src/test/java - contains unit tests
And dependency for the project 1 (hrm-domain)
My problem is when I run this project I am getting error as follows:
... 38 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Not an entity: class com.hrm.ws.data.domain.Employee
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:149)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1429)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:844)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:786)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
... 40 more
**Caused by: java.lang.IllegalArgumentException: Not an entity: class** com.hrm.ws.data.domain.Employee
at org.hibernate.ejb.metamodel.MetamodelImpl.entity(MetamodelImpl.java:160)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:52)
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:61)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:145)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:83)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:66)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:146)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:120)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:39)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
... 48 more
I am wondering about this issue, because when I put domain object (Employee.java) in my spring project it self rather separate jar it works fine. This issue only happens it gives as a separate jar. If any one has experience about scenario like that please give me a help.

I also had the same problem. Mine was that I didn't supply the packagesToScan property in the entityManagerFactory bean, so Spring couldn't load the Entities. Check out the emf bean declaration in your spring configuration xml. The following is a EMF declaration I hope it could help you to get rid the error:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.hrm.ws.data.domain" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>

You're not scanning the com.hrm.ws.data.domain package for beans annotated with #Entity so the spring container has no knowledge of your entities and therefore producing an exception. Add the following lines to your persistance-context.xml config file:
<context:annotation-config />
<context:component-scan base-package="com.hrm.ws.data.domain" />
You'll also need to change your root xml element as follows so it the context elements are recognized:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
And, if you haven't already, add the spring-context dependency to your pom file.

Use one of the following option :-
context:component-scan
base-package="Your Base Package Name" in spring.xml file
set packagesToScan property on the entityManagerFactory
use persistence.xml and list all entities there.

Related

Not able to getCurrentSession() from SessionFactory , Getting HibernateException

Its my first very simple Spring-Hibernate application.
i am getting this
'Could not obtain transaction-synchronized Session for current thread ' error
when i am trying to get current session from SessionFactory.
I tried following things..
used #Repository , #Transactional in my dao.
configured TransactionManager.
used # Entity on my entity class.
my root-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-
context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- <context:property-placeholder
location="classpath:../properties/db.properties" /> -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/hib" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.nin.entity" />
<property name="hibernateProperties">
<props>
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.default_schema">hib</prop>
</props>
</property>
<tx:annotation-driven transaction-manager="TransactionManager" />
<bean id="TransactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix">
<value>/WEB-INF/view/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
My dispatcherServlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-
3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-
context-3.1.xsd">
<context:component-scan base-package="com.nin"></context:component-scan>
<mvc:annotation-driven/>
</beans>
My Dao class
package com.nin.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.nin.entity.Student;
#Repository
public class DaoImpl {
#Autowired
private SessionFactory sf;
#Transactional
public void register (Student st){
sf.getCurrentSession(); //Getting Error at this line.
// Session session = sf.getCurrentSession();
// session.save(st);
}
}
lastly my entity class
package com.nin.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="student")
public class Student {
#Column(name="name")
private String name;
#Id
#Column(name="rollno")
private String rollno;
#Column(name="password")
private String password;
#Column(name="city")
private String city;
public Student(){};
//and getters and setters..
Thanks in advance and sorry for my English & representation of question.
The problem is that your Hibernate and transaction configuration is in the configuration file loaded by the ContextLoaderListener. Whereas your components are loaded by the DispatcherServlet due to the <component-scan /> in that file.
When using things like transactions those are applied through AOP. AOP is applied through post processing beans. Post processing only applies to beans in the same context, else you might get strange results.
As you haven't 2 contexts, the AOP stuff is in a different one then the actual components you want to apply AOP to.
You can either put everything in a single context or move the <context:component-scan /> to the configuration containing the transactional configuration.
Note: If you have the same <component-scan /> in the configuration file all of your components will be loaded twice and as the nearest to the component (in this case controller) is being used you have the same problem.

test hibernate entities with spring

I try to tests how hibernate Entities are persisted to database. I have 5 tests for 3 Entitites. All my attempts are unsuccessful((( I tried to use #Transactional annotation to bind each test to one transaction. But I could not (tried all combinations). Now I try to test it manually creating sessions and transactions. But now problem is that I dont know how to create one session for all tests. I tried #BeforeClass, but here problem is that it is static and I use Spring beans for session creation. Any ideas how I can test hibernate Entities?
You can use a dedicated database like HSQLDB for testing you entities via DAO test classes.
You will need a:
Maven test profile
Spring configuration file (test context)
Script SQL to insert some data
DAO class test.
Maven test profile :
<profile>
<id>test</id>
<properties>
<jpa.dialect>org.springframework.orm.jpa.vendor.HibernateJpaDialect</jpa.dialect>
<jpa.vendor.adapter>HibernateJpaVendorAdapter</jpa.vendor.adapter>
<jdbc.dialect>org.hibernate.dialect.HSQLDialect</jdbc.dialect>
<jdbc.url>jdbc:hsqldb:mem:testDatabase</jdbc.url>
<jdbc.driver>org.hsqldb.jdbcDriver</jdbc.driver>
<jdbc.username>sa</jdbc.username>
<jdbc.password></jdbc.password>
<jdbc.format_sql>true</jdbc.format_sql>
<jdbc.show_sql>true</jdbc.show_sql>
<!-- import.sql is read : it must have this name and be in classpath -->
<jpa.generateDdl>true</jpa.generateDdl>
<hibernate.format_sql>true</hibernate.format_sql>
<hibernate.hbm2ddl.auto>create</hibernate.hbm2ddl.auto>
</properties>
</profile>
Spring test-applicationContext.xml file :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- enables interpretation of the #PersistenceUnit/#PersistenceContext
annotations providing convenient access to EntityManagerFactory/EntityManager -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<context:component-scan base-package="foo.bar.dao">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Repository" />
</context:component-scan>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="jpaLibrary" />
<property name="jpaDialect">
<bean class="${jpa.dialect}" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.${jpa.vendor.adapter}">
<property name="showSql" value="${jdbc.show_sql}" />
<property name="databasePlatform" value="${jdbc.dialect}" />
<!-- On genere la BDD au demarrage -->
<property name="generateDdl" value="${jpa.generateDdl}" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
<context:spring-configured />
<context:annotation-config />
</beans>
import.sql (authors for instance):
INSERT INTO `testDatabase`.`authors`(author_id, name) VALUES
(1, "JRR Tolkien"),
(2, "Albert Camus"),
(3, "Victor Hugo");
...
Finally, the class to test your DAO (then entities) :
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import foo.bar.dao.BookDao;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/test-applicationContext.xml" })
public class BookDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
#Autowired
private BookDao bookDao;
private int initialSize = 0;
#Before
public void init() {
initialSize = bookDao.findAll().size();
}
#Test
public void getAllBooks() {
assertEquals(12, initialSize);
}
...
}

Spring MVC JdbcTemplate Transactional Annotation does not work

I have two insert operation in one http post request. something like
#Service
public class StudentService {
#Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public int create(final Student student) {
// insert into table 1
// insert into table 2 using id return from insert 1, but something BAD happen here
}
}
so, I added #Transactional at method level as shown above.
In order to make it work, I added this tx:annotation-driven
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
so my app-servlet.xml looks like
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<mvc:annotation-driven />
<mvc:resources mapping="/res/**" location="/res/" />
<context:component-scan base-package="com.app" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="dataSource" name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://xxx:3306/AppDb" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
</beans>
the component-scan will basically scan all class include controller, service, model, viewmodel, helper class etc.
If I remove the tx:annotation-driven, the #transactional won't work.
But once I add this tx:annotation-driven, some error starts to appear, like
Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.app.service.StudentService com.app.controller.HomeController.studentRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentService' defined in file [/path/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/MathSchool/WEB-INF/classes/com/app/service/StudentService.class]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/cglib/transform/impl/MemorySafeUndeclaredThrowableStrategy
How can I make this #transactional work.
Thanks to #Jens
My project using spring 4.1.6 and spring security 3.2.7
According to this documentation Migrating from Spring Security 3.x to 4.x (XML Configuration)
Spring Security 4 now requires Spring 4 (Spring 4.0 or 4.1, I guess). Conveniently, Spring Security
3.2.x works with Spring 3.2.x and Spring 4 (Spring 4.0 Only, I guess).
The only thing I did is downgrade Spring 4.1 to Spring 4.0

Error creating bean.Injection of autowired dependencies failed. Could not autowire

Hello I´m newbie in spring mvc, i´m using #autowired but i don´t know the solution. Thx you. Sorry but my english, i´m learning it.
I have two class Empresa.java and Ldiario.java. Empresa.java it works.
UPDATE
I updated the following code but I have the same error.
app-config.xml
<!-- Hibernate Session Factory -->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan" value="com.atorresbr.springapp.**"/>
and I added a bean.
<bean id="diarioBean" class="com.atorresbr.springapp.bean.DiarioBean"/>
Error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'diarioBean': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.atorresbr.springapp.model.Ldiario com.atorresbr.springapp.bean.DiarioBean.ldiario; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.atorresbr.springapp.model.Ldiario] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
DiarioBean.java
#ManagedBean(name="diarioBean")
#SessionScoped
#Component
public class DiarioBean {
#Autowired
private Ldiario ldiario;
#Autowired
private Ldiario selectedLdiario;
public DiarioBean(){
}
public Ldiario getLdiario() {
return ldiario;
}
public void setLdiario(Ldiario ldiario) {
this.ldiario = ldiario;
}
public Ldiario getSelectedLdiario() {
return selectedLdiario;
}
public void setSelectedLdiario(Ldiario selectedLdiario) {
this.selectedLdiario = selectedLdiario;
}
}
Ldiario.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import java.io.Serializable;
import java.sql.Blob;
import java.util.Date;
#Entity
#Table(name = "LDIARIO2014")
public class Ldiario implements Serializable{
#Id
#Column(name = "CLAVE")
#GeneratedValue private Integer CLAVE;
#ManyToOne
#JoinColumn (name = "empresa")
private Empresa empresa;
#Column(name = "ASIENTO")
private Integer ASIENTO;
#Column(name = "ORDEN")
private Integer ORDEN;
#Column(name = "FECHA")
private Date FECHA;
app-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- Scans the classpath of this application for #Components #Service #Repository to deploy as
beans -->
<context:component-scan base-package="com.atorresbr.springapp" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven />
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="diarioBean" class="com.atorresbr.springapp.bean.DiarioBean"/>
<!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with
username root and blank password. Change below if it's not the case -->
<bean id="myDataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"
p:validationQuery="${jdbc.validationQuery}" />
<!--
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/pizzashop"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="validationQuery" value="SELECT 1"/>
</bean> -->
<!-- Hibernate Session Factory -->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan" value="com.atorresbr.springapp.**"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<!-- Activates annotation based transaction management -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

Tranaction Manager in Spring JPA DAO

I've used the following configuration in spring and JPA,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="entityManger"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="JPA-01" />
</bean>
<bean id="dao" class="springdao.MessageDAO" />
</beans>
and my persistence.xml is,
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="JPA-01">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/Hibernate" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="password" />
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="20" />
<property name="hibernate.c3p0.timeout" value="300" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.idle_test_period" value="3000" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<!-- <property name="hibernate.hbm2ddl.auto" value="create" />
-->
</properties>
</persistence-unit>
</persistence>
and my junit is,
package test;
import junit.framework.Assert;
import model.Message;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import dao.MessageDAO;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:SpringDAOTest.xml"})
public class SpringDAOTest {
#Autowired
springdao.MessageDAO dao;
#Test
public void testGetMessageById() {
Message message = dao.getMessageById("1");
Assert.assertNotNull(message);
System.out.println(message);
}
#Test
public void testPersistMEssage() {
Message message = new Message();
message.setMessage("Hello World This is the second Message");
dao.persistMessage(message);
}
#Test
public void testUpdateMessage() {
String updatedMessage = "Updated Message for ID 1";
dao.updateMessage(updatedMessage, 1);
}
// TODO updateMessageID
#Test
public void testUpdateMessageID() {
String updatedMessage = "Updated Message for ID 1 with 25";
dao.updateMessageID(updatedMessage, 1);
}
}
I've following questions,
I've autowired the persistence context. I want to assert that the current persistent context is associtated or not?
I've not used the transaction manager configured in the applicationcontext.xml. Just by annotating the classes, I'm able to configure transactions to the services.
I want to get the entity transaction id, so that I want to assert that for the entire service (which involves a lot of daos) uses the same transaction.
1) Provide a getter method for EntityManager in your MessageDAO and use assertNotNull (Although not advisable and not required to test this scenario; you should be testing only your business logic and trust the framework will correctly associate the EntityManager)
2) Reading data from database doesn't require transaction. However, writing data to database does require transaction. Therefore you need to configure a transaction manager for your persistent operation like below
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
You can make a method execute under a transaction in two ways
XML configuration
#Transactional annotation
Annotating your method using #Transactional without a TransactionManager will silently ignore it.
3) I'm not aware of retrieving a transaction id.
However, the primary intention of using a framework like Spring is that someone has already tested infrastructure code for you and you can concentrate on testing only your business logic. Trying to retest may not be a good idea.
As you are using entity manager as the data-access API you can use following transaction manager configuration
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="dataSource"/>
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
By default this transaction manager picks up the datasource bean if named "dataSource" and "entityManagerFactory". This transaction manager variety binds the entity manager from the specified entitymanager factory with the current thread. Also it would be worthwhile to have a look at its documentation.

Resources