Spring JpaTransactionManager with Nested transactions - java

I have following spring configuration.
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="nestedTransactionAllowed" value="true" />
</bean>
<bean id='entityManagerFactory'
class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
<property name="persistenceUnitName" value="test" />
<property name='dataSource' ref='dataSource' />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
</bean>
<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/testdb" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
And i have created following entity.
#Entity(name="testtable")
public class Testtable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(unique=true, nullable=false)
private int testid;
#Column(length=10)
private String description;
public Testtable() {
}
public int getTestid() {
return this.testid;
}
public void setTestid(int testid) {
this.testid = testid;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
}
Now I want to test the nested transaction behavior with this setup. So I have created following test class.
#TransactionConfiguration(defaultRollback=false)
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:context-test.xml")
public class TableTest {
#Autowired
private TesttableRepository testtableRepository;
#Test
#Transactional
public void testMethod()
{
Testtable entry = new Testtable();
entry.setDescription("ABC");
entry = testtableRepository.save(entry);
TestObj t = new TestObj(testtableRepository);
t.testNestedTransactional();
entry.setDescription("ABCEE");
testtableRepository.save(entry);
assertNotNull(entry.getTestid());
}
}
public class TestObj {
public TestObj(TesttableRepository testtableRepository){
this.testtableRepository = testtableRepository;
}
private TesttableRepository testtableRepository;
#Transactional(propagation=Propagation.NESTED )
public void testNestedTransactional(){
Testtable entry1 = new Testtable();
entry1.setDescription("RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR");
testtableRepository.save(entry1);
}
}
The testNestedTransactional() method in TestObj.java should fail because of database constraint violation (Max length for field description is 10). Even though this method fail I expect "ABCEE" value to be saved in database. Is this correct with nested transaction behavior? How can I achieve this goal?

The problem is that you create TestObj manually. You should do it using Spring context (declare it in context as a bean and autowire in the test).
Spring will wrap this bean in a proxy to make it transactional. In your case it is a plain old Java object without transactional behavior.

Related

Oracle/Hibernate insert - java.lang.ArrayIndexOutOfBoundsException: 8

I am getting exception while inserting records into table.
java.lang.ArrayIndexOutOfBoundsException: 8/ org.hibernate.exception.GenericJDBCException: could not prepare statement
i used JNDI datasource/Oracle for creating hibernate sessionFactory.
Here is the SessionFactory configuration :
<beans:bean id="jndiDataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<beans:property name="jndiName" value="java:jboss/datasources/TestDS" />
</beans:bean>
<beans:bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="jndiDataSource" />
<beans:property name="packagesToScan" value="com.majesco.integration.model" />
<beans:property name="configLocation" value="classpath:hibernate.cfg.xml" />
</beans:bean>
here hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.Oracle12cDialect</property>
<property name="show_sql">true</property>
</session-factory>
</hibernate-configuration>
Here model :
#Entity
#Table(name="EVENT_AUDIT")
public class MessageControl implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="LMESSAGESEQ")
private Integer messageseq;
#Column(name="NMESSAGEID")
private Integer messageid;
#Column(name="STRMESSAGE_CD")
private String messagecd;
#Column(name="STRQUEUE_CD")
private String queuecd;
#Column(name="NMODULEID_FROM")
private String moduleidfrom;
#Column(name="NMODULEID_TO")
private String moduleidto;
#Column(name="NMESSAGE_STATUS")
private String messagestatus;
#Column(name="STRTRXNBR")
private String transactionNBR;
#Column(name="STRUUID")
private String uuid;
//getter and setter
}
Here DAO code:
public class MessageAuditDaoImpl implements AuditDao{
#Autowired
#Qualifier("sessionFactory")
private SessionFactory factory;
#Override
public void saveAuditMessage(MessageControl messageControl) {
try {
session=factory.openSession();
session.save(messageControl);
logger.info("Saved Message");
session.close();
} catch (Exception e) {
logger.error("Exception Occured"+e);
}
}
}
My code is working fine if I insert parameter lower than 8 and getting the exception for parameter grater than 8.
What's the issue or anything i missed in the code?

SpringJDBC ClassPathXmlApplicationContext unable to load getbean from xml in resources

I am noob in java. i want to insert data into employe table.
Err: No bean named 'employeeDAO.class' is defined.
my code structure:
This is my code.
file: com.vm.springjdbc.app.App.java
public class App {
private ApplicationContext context;
private EmployeeDAO employeeDAO;
public static void main(String[] args) {
context = new ClassPathXmlApplicationContext("Spring-Datasource.xml");
employeeDAO = (EmployeeDAO) context.getBean("employeeDAO.class");
}
}
file: com.vm.springjdbc.model.Employee.java
public class Employee {
private int id;
private String name;
private String mobile;
setter & getter
}
file: com.vm.springjdbc.DAO.EmployeDAO.java
public class EmployeeDAO extends JdbcDaoSupport {
public void insert(Employee emp){
}
}
Xml file in resources:src/resources/Spring-Datasource.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/synapse4" />
<property name="username" value="root" />
<property name="password" value="admin" />
</bean>
<bean id="employeeDAO" class="com.vm.springjdbc.DAO.EmployeeDAO">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
Please help me to sort it out
You should make the EmployeeDAO as interface and make an impl class for this EmployeeDAOImpl as follows:
EmployeeDAO.java
public interface EmployeeDAO
{
public void insert(Employee employee);
}
EmployeeDAOImpl.java
public class EmployeeDAOImpl extends JdbcDaoSupport implements EmployeeDAO
{
public void insert(Employee employee){
//insertion implementation
}
}
and make the following changes in Spring-Datasource.xml
<bean id="employeeDAO" class="com.vm.springjdbc.DAO.EmployeeDAOImpl">
<property name="dataSource" ref="dataSource" />
</bean>
Also, please do not use .class in
employeeDAO = (EmployeeDAO) context.getBean("employeeDAO.class");
change it to
employeeDAO = (EmployeeDAO) context.getBean("employeeDAO");

HibernateException: saveOrUpdate is not valid without active transaction

Perhaps this question has been asked severally but am not able to find a solution to this. I am new to Spring and trying to working on a simple project to integrate Spring with Hibernate 4 using annotations. Whenever i click the user form to save to DB it throws this exception:
HTTP Status 500 - Request processing failed; nested exception is org.hibernate.HibernateException: saveOrUpdate is not valid without active transaction
What am I doing wrong? My code is below:
User.java
#Entity
#Table(name="SpringUsers")
public class User implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "userId")
private int id;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
UsDAOImpl.java
#Repository
public class UserDAOImpl implements UserDAO{
#Autowired
private SessionFactory sessionFactory;
public UserDAOImpl(){}
public UserDAOImpl( SessionFactory sessionFactory){
this.sessionFactory= sessionFactory;
}
#Override
#Transactional
public List<User> list() {
List<User> listUser = sessionFactory.getCurrentSession()
.createCriteria(User.class).list();
return listUser;
}
#Override
#Transactional
public void saveOrUpdate(User user) {
sessionFactory.getCurrentSession().saveOrUpdate(user);
}
#Override
#Transactional
public void delete(int id) {
User userToDelete = new User();
userToDelete.setId(id);
sessionFactory.getCurrentSession().delete(userToDelete);
}
#Override
#Transactional
public User get(int i) {
String hql = "from User where id=" + i;
Query query = sessionFactory.getCurrentSession().createQuery(hql);
List<User> listUser = (List<User>) query.list();
if (listUser != null && !listUser.isEmpty()) {
return listUser.get(0);
}
return null;
}
}
user-servlet.xml
<context:component-scan base-package="com.myspringapp.controller"/>
<mvc:annotation-driven/>
<context:annotation-config />
<!-- <tx:annotation-driven />-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:XE"/>
<property name="username" value="system"/>
<property name="password" value="henry"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.myspringapp.model.User</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<constructor-arg ref="sessionFactory"/>
</bean>
<bean id="userDao" class="com.myspringapp.dao.UserDAOImpl">
<constructor-arg ref="sessionFactory"/>
</bean>
<!-- <tx:annotation-driven transaction-manager="transactionManager"/>-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
Uncomment this line and it should work:
<tx:annotation-driven />

Getting Error in Spring Mvc

I am getting following error....
java.lang.IllegalStateException: **Neither BindingResult nor plain target object for bean name 'course' available as request attribute**
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144)
at
Model Class:
#Entity
#Table(name="course" ,schema = "practise5")
public class Course implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#GeneratedValue(strategy=GenerationType.AUTO)
#Id
private int id;
#Column(name="Name")
private String Name;
#ManyToMany(mappedBy="courseSet")
private Set<Person> personSet;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public Set<Person> getPersonSet() {
return personSet;
}
public void setPersonSet(Set<Person> personSet) {
this.personSet = personSet;
}
}
Controller:
#RequestMapping(value="/addCourse",method= RequestMethod.POST)
public #ResponseBody String addCourse(#ModelAttribute("course") Course course, Model model)
{
courseServise.addcourse(course);
return "redirect:addEmployee";
}
Jsp:
<form:form commandName="course" action="addCourse" method="POST">
<form:input path="CourseName" id="course" required="required"/>
<input type="submit" value="Submit">
</form:form>
............................................................................................................................................................
<context:annotation-config />
<context:component-scan base-package="com.spring" />
<mvc:annotation-driven />
<mvc:resources location="/WEB-INF/" mapping="/**" />
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="resources/messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource" 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}" />
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.spring.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<!-- <prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop> -->
</props>
</property>
</bean>
I just add the following code in my controller...
Second thing is that you have to first redirect your index.jsp file to some other file...
#RequestMapping(method = RequestMethod.GET)
public String addEmployee(#ModelAttribute("a") A a, Model model,HttpServletRequest request)
{
return "addEmployee";
}
You don't match the correct URL in your JSP file.
Change this line on your JSP file :
<form:form commandName="course" action="addCourse" method="POST">
For:
<form:form commandName="course" action="/addCourse" method="POST">
Else, you can change your mapping on your controller:
#RequestMapping(value="/addCourse",method= RequestMethod.POST)
For:
#RequestMapping(value="addCourse",method= RequestMethod.POST)
as said in this post, error might occur while loading the jsp itself, and
more over binding might fail for below reasons
The binding results can be examined via the BindingResult interface,
extending the Errors interface: see the getBindingResult() method.
Missing fields and property access exceptions will be converted to
FieldErrors, collected in the Errors instance, using the following
error codes:
> Missing field error: "required"
> Type mismatch error: "typeMismatch"
> Method invocation error: "methodInvocation"
so check any type mismatches or field you might have missed, as i had faced this issue personally

org.hibernate.MappingException: Unknown entity:

I really want to understand what is going on with my code.
I have a standalone application which uses spring and Hibernate as JPA and I am trying to run the test using a single main Class
My main class
package edu.acct.tsegay.common;
import edu.acct.tsegay.model.User;
import edu.acct.tsegay.business.IUserBusinessObject;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
try {
ApplicationContext context = new ClassPathXmlApplicationContext(
"Spring3AndHibernate-servlet.xml");
IUserBusinessObject userBusinessObject = (IUserBusinessObject) context
.getBean("userBusiness");
User user = (User) context.getBean("user1");
user.setPassword("pass");
user.setUsername("tsegay");
System.out.println(user.getPassword());
userBusinessObject.delete(user);
User user2 = new User();
user2.setUsername("habest");
user2.setPassword("pass1");
System.out.println(user2.getPassword());
/*
* userBusinessObject.save(user2);
*
* User user3 = userBusinessObject.searchUserbyId("tsegay");
* System.out.println("Search Result: " + user3.getUsername());
*/
System.out.println("Success");
} catch (Exception e) {
e.printStackTrace();
}
}
}
my application context is:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- data source -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="test" />
<property name="password" value="password" />
</bean>
<!-- session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- exposed person business object -->
<bean id="userBusiness" class="edu.acct.tsegay.business.UserBusinessObject">
<property name="userDao" ref="userDao" />
</bean>
<bean id="user1" class="edu.acct.tsegay.model.User">
<property name="username" value="tse" />
<property name="password" value="pass" />
</bean>
<!-- Data Access Object -->
<bean id="userDao" class="edu.acct.tsegay.dao.UserDao">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
My User Model is:
package edu.acct.tsegay.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Version;
import org.hibernate.annotations.NaturalId;
#Entity
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String username;
private String password;
private Integer VERSION;
#Version
public Integer getVERSION() {
return VERSION;
}
public void setVERSION(Integer vERSION) {
VERSION = vERSION;
}
#NaturalId
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
My DAO is:
package edu.acct.tsegay.dao;
import edu.acct.tsegay.model.User;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;
#Repository
public class UserDao implements IUserDao {
private SessionFactory sessionFactory;
private HibernateTemplate hibernateTemplate;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public void save(User user) {
// TODO Auto-generated method stub
// getHibernateTemplate().save(user);
this.hibernateTemplate.save(user);
}
public void delete(User user) {
// TODO Auto-generated method stub
this.hibernateTemplate.delete(user);
}
public User searchUserbyId(String username) {
// TODO Auto-generated method stub
return this.hibernateTemplate.get(User.class, username);
}
}
And this my stacktrace error when i run the program:
pass
org.springframework.orm.hibernate3.HibernateSystemException: Unknown entity: edu.acct.tsegay.model.User; nested exception is org.hibernate.MappingException: Unknown entity: edu.acct.tsegay.model.User
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:679)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:837)
at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:833)
at edu.acct.tsegay.dao.UserDao.delete(UserDao.java:34)
at edu.acct.tsegay.business.UserBusinessObject.delete(UserBusinessObject.java:30)
at edu.acct.tsegay.common.App.main(App.java:23)
Caused by: org.hibernate.MappingException: Unknown entity: edu.acct.tsegay.model.User
at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:580)
at org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1365)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:100)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:74)
at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:793)
at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:771)
at org.springframework.orm.hibernate3.HibernateTemplate$25.doInHibernate(HibernateTemplate.java:843)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
... 6 more
You have to list your classes in your session factory configuration. You can have your entities auto-discovered if you are using EntityManager.
In order to use annotations with hibernate and spring, you have to use AnnotationSessionFactoryBean:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="annotatedClasses">
<list>
<value>edu.acct.tsegay.model.User</value>
</list>
</property>
....
</bean>
Also, it is rather strange that your User entity is a spring bean. You don't need that. Hibernate entities are supposed to be created with the new operator.
I've encountered the same problem and didn't find any good answer for this
What worked for me was to declare my entity class in the persistence.xml file:
<persistence ...>
<persistence-unit ...>
<class>com.company.maenad.core.model.News</class>
<class>com.company.maenad.core.model.AdExtraInfo</class>
</persistence-unit>
</persistence>
In addition to Bozho answer, if you are using spring + hibernate with annotation then in your session factory bean you can register your bean like below:
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(appContext.getBean(HikariDataSource.class));
localSessionFactoryBean.setAnnotatedClasses(
AppUser.class, Assignment.class
);

Categories

Resources