I'm trying to write a simple Spring app and I'm having trouble getting the Spring Repository to work right. I'm getting a NullPointerException at com.impetus.kundera.query.KunderaQuery.initEntityClass(KunderaQuery.java:390).
The exception is ultimately caused by collectionRepository.findAll().
Full stack trace:
java.lang.NullPointerException
at com.impetus.kundera.query.KunderaQuery.initEntityClass(KunderaQuery.java:390)
at com.impetus.kundera.query.KunderaQuery.postParsingInit(KunderaQuery.java:353)
at com.impetus.kundera.query.QueryResolver.getQueryImplementation(QueryResolver.java:80)
at com.impetus.kundera.persistence.PersistenceDelegator.getQueryInstance(PersistenceDelegator.java:557)
at com.impetus.kundera.persistence.PersistenceDelegator.createQuery(PersistenceDelegator.java:527)
at com.impetus.kundera.persistence.EntityManagerImpl.createQuery(EntityManagerImpl.java:379)
at com.impetus.kundera.persistence.EntityManagerImpl.createQuery(EntityManagerImpl.java:717)
at com.impetus.kundera.persistence.EntityManagerImpl.createQuery(EntityManagerImpl.java:704)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
at com.sun.proxy.$Proxy33.createQuery(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:471)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:264)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:358)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy35.findAll(Unknown Source)
at com.example.spring.controller.CollectionController.listCollections(CollectionController.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
I've debugged it nearly as far as I can go and there's a few causes for concern. Going back to the EntityManagerImpl on line 704 the CriteriaQueryTranslator translates the CriteriaQuery to SELECT FROM CollectionEntity null.
This query obviously has problems. So going deeper into the CriteriaQueryTranslator.translate method (line 122):
builder.appendAlias(from.getAlias() != null ? from.getAlias() : select.getAlias());
The from.getAlias() returns null, therefore the select.getAlias() is appended to the builder (which is also null). So the alias is what is causing the weird JPQL syntax.
So is this a bug in Kundera or do I have some Spring configuration wrong?
The collectionRepository.findAll() in the controller is what generates this error.
Here's all my configuration and subject java files:
CollectionController:
import com.example.spring.hibernate.CollectionEntity;
import com.example.spring.repositories.CollectionRepository;
import com.example.spring.services.CollectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.annotation.Resource;
#Controller
public class CollectionController {
#Autowired
private CollectionRepository collectionRepository;
#RequestMapping(value="/collections", method= RequestMethod.GET)
public String listCollections(ModelMap model) {
model.addAttribute("collection", new CollectionEntity());
// THE ERROR HAPPENS HERE (collectionRepository.findAll())
model.addAttribute("collections", collectionRepository.findAll());
return "collections";
}
}
CollectionRepository:
import com.example.spring.hibernate.CollectionEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CollectionRepository extends JpaRepository<CollectionEntity, Long> {
}
CollectionEntity:
import javax.persistence.*;
import java.util.Date;
#Entity(name="collection")
#Table(name = "collection", schema = "", catalog = "mydb")
public class CollectionEntity {
#Id
#Column(name = "collection_id")
private int collectionId;
#Basic
#Column(name = "collection_name")
private String collectionName;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "collection_type_id")
private CollectionTypeEntity collectionType;
#Column(name = "active")
private boolean active;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_at")
private Date createdDate;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated_at")
private Date updatedDate;
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public Date getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
public int getCollectionId() {
return collectionId;
}
public void setCollectionId(int collectionId) {
this.collectionId = collectionId;
}
public String getCollectionName() {
return collectionName;
}
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
public CollectionTypeEntity getCollectionType() {
return collectionType;
}
public void setCollectionTypeId(CollectionTypeEntity collectionType) {
this.collectionType = collectionType;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}
persistence.xml:
<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="maria_pu">
<provider>com.impetus.kundera.KunderaPersistence</provider>
<class>com.example.spring.hibernate.CollectionEntity</class>
<class>com.example.spring.hibernate.CollectionTypeEntity</class>
<properties>
<property name="kundera.client.lookup.class" value="com.impetus.client.rdbms.RDBMSClientFactory" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.connection.driver_class" value="org.mariadb.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/mydb" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.current_session_context_class" value="thread"/>
</properties>
</persistence-unit>
</persistence>
web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Hello World Application</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
and finally the dispatcher.servlet.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.example.spring" />
<jpa:repositories base-package="com.example.spring.repositories"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="maria_pu"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
As I said I'm new to Spring so I may just be missing some configuration parameters. Any help is greatly appreciated!
Related
I'm trying to use Multithread in my app to do some tasks that take some minutes to complete.
The idea is that I have n number of objects so I want those to be processed in parallel and without making the user (web app) wait for them to be completed (as it takes several minutes). Also in other case (when the amount of object is one), I want to wait until the process is done so the user can see the result.
But I'm having some issues.
So my code is:
RunSomeTaskServiceImpl:
public class RunSomeTaskServiceImpl extends CommonService implements RunSomeTaskService{
#Async
#Override
public Future<Response> doTasks(Student student) {
Response response = new Response();
//do Tasks
return new AsyncResult<Response>(response);
}
}
RunSomeTaskService:
public interface RunSomeTaskService{
public Future<Response> doTasks(Student student);
}
StudentServiceImpl:
#Autowired
RunSomeTaskService runSomeTaskService;
#Override
Transactional
public Response save(StudentBO[] students) throws Exception {
...
for (StudentBO student : students) {
....
Future<Response> response = runSomeTaskService.doTasks(student);
if(students.size() == 1){
return response.get();
}
}
....
}
So when there is more than one student, I get the error:
12:17:44.040 [DEMO-4] DEBUG o.h.r.t.b.j.i.JdbcResourceLocalTransactionCoordinatorImpl - JDBC transaction marked for rollback-only (exception provided for stack trace)
java.lang.Exception: exception just for purpose of providing stack trace
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.markRollbackOnly(JdbcResourceLocalTransactionCoordinatorImpl.java:265) [hibernate-core-5.0.6.Final.jar:5.0.6.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:156) [hibernate-core-5.0.6.Final.jar:5.0.6.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) [hibernate-core-5.0.6.Final.jar:5.0.6.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231) [hibernate-core-5.0.6.Final.jar:5.0.6.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65) [hibernate-core-5.0.6.Final.jar:5.0.6.Final]
at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:581) [spring-orm-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) [spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) [spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485) [spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291) [spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) [spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:108) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.interceptor.AsyncExecutionAspectSupport$CompletableFutureDelegate$1.get(AsyncExecutionAspectSupport.java:237) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590) [na:1.8.0_171]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]
12:17:44.043 [DEMO-4] DEBUG o.s.o.h.HibernateTransactionManager - Initiating transaction rollback after commit exception
org.hibernate.AssertionFailure: null id in com.app.model.FieldValue entry (don't flush the Session after an exception occurs)
And when there is just one:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions. Collection : <unknown>
Collection contents: [[]]
at org.hibernate.collection.internal.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:627)
at org.hibernate.event.internal.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:46)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:104)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:65)
at org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:59)
at org.hibernate.event.internal.AbstractVisitor.process(AbstractVisitor.java:126)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:227)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:92)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:648)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:640)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:635)
at com.app.dao.CommonDaoImpl.addOrUpdate(CommonDaoImpl.java:28)
at com.app.services.ExtractDataServiceImpl.doExtraction(ExtractDataServiceImpl.java:361)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:108)
at org.springframework.aop.interceptor.AsyncExecutionAspectSupport$CompletableFutureDelegate$1.get(AsyncExecutionAspectSupport.java:237)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Student model
package com.app.model;
// Generated 18-jul-2018 15:27:32 by Hibernate Tools 5.2.10.Final
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
/**
* Student generated by hbm2java
*/
#Entity
#Table(name = "student", catalog = "school_db", uniqueConstraints = #UniqueConstraint(columnNames = "code"))
public class Student implements java.io.Serializable {
private Integer id;
private String name;
private Grade grade;
private Set<Subject> subjects = new HashSet<Subject>(0);
public Student() {
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "grade")
public Grade getGrade() {
return this.grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "student")
public Set<Subject> getSubjects() {
return this.subjects;
}
public void setSubjects(Set<Subject> subjects) {
this.subjects = subjects;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "student")
public Set<Subject> getSubjects() {
return this.subjects;
}
}
spring-config.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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.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:annotation-config />
<!-- <context:component-scan base-package="com.app.controller, com.app.security" /> -->
<context:component-scan base-package="com.app.controller" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<mvc:annotation-driven />
....
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.app.model.Student</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
...
So could you please help me to avoid this issues?
I have Spring MVC app with Hibernate. Earlier I had a class which works with session(database) for each entity and everything worked good. Now, I have abstract Dao class which is inherited by one class for each entity. When I want to insert new data in database, everything works good. But when I want to update the data, they reach the controller (I can print them in console) but Hibernate doesn't generate sql code for update. I turned on property of Hibernate to show sql and I saw that hibernate generated all sql queries except UPDATE. All methods in Abstract class work, except update method.
And one interesting thing is that I don't get any erors in console.
This is Intersection class
#Entity
#Table(name = "intersections")
public class Intersection implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "symbol")
private Integer symbol;
#Size(max = 256)
#Column(name = "title")
private String title;
#OneToMany(mappedBy = "intersection",cascade = CascadeType.ALL)
private List<Access> accessList;
Access class
#Entity
#Table(name = "accesses")
public class Access implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "symbol")
private Integer symbol;
#Size(max = 50)
#Column(name = "title")
private String title;
#JoinColumn(name = "intersection", referencedColumnName = "id")
#ManyToOne(cascade = CascadeType.ALL)
private Intersection intersection;
Abstract Class
public abstract class AbstractDao<T, I, A, P, ID extends Serializable> implements DaoInterface<T, I, A, P, ID>{
#Autowired
private SessionFactory sessionFactory;
private Class<T> classType;
public AbstractDao(){
ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
this.classType = (Class<T>)type.getActualTypeArguments()[0];
}
#Override
public void insert(T t) {
Session session = sessionFactory.getCurrentSession();
session.save(t);
}
#Override
public void update(T t) {
Session session = sessionFactory.getCurrentSession();
session.update(t);
}
#Override
public List<T> getAll() {
Session session = sessionFactory.getCurrentSession();
Criteria c = session.createCriteria(classType);
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.addOrder(Order.asc("symbol"));
List<T> list = c.list();
return list;
}
#Override
public T getById(ID id) {
Session session = sessionFactory.getCurrentSession();
T a = (T)session.get(classType, id);
return a;
}
#Override
public List<T> getByIntersection(I i) {
Session session = sessionFactory.getCurrentSession();
Criteria c = session.createCriteria(classType);
c.add(Restrictions.eq("intersection", i));
c.addOrder(Order.asc("symbol"));
List<T> list = c.list();
return list;
}
#Override
public List<T> getByAccess(A a) {
Session session = sessionFactory.getCurrentSession();
Criteria c = session.createCriteria(classType);
c.add(Restrictions.eq("access", a));
c.addOrder(Order.asc("symbol"));
List<T> list = c.list();
return list;
}
#Override
public List<T> getByPole(P p) {
Session session = sessionFactory.getCurrentSession();
Criteria c = session.createCriteria(classType);
c.add(Restrictions.eq("pole", p));
c.addOrder(Order.asc("symbol"));
List<T> list = c.list();
return list;
}
AccessDao
#Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public class AccessDao extends AbstractDao<Access, Intersection, Access, Pole, Integer>{
}
Method in Controller
#RequestMapping(value = "/access", method = RequestMethod.POST)
public String accessUpdate(
#RequestParam Integer idInt,
#RequestParam Integer idAccess,
#RequestParam String symbol,
#RequestParam String title,
ModelMap model){
String naslov = "Ažuriranje prilaza";
model.addAttribute("naslov", naslov);
List<Intersection> intersections = intersectionDao.getAll();
model.addAttribute("intersections", intersections);
Intersection i = intersectionDao.getById(idInt);
Access a = (Access) accessDao.getById(idAccess);
a.setIntersection(i);
a.setSymbol(Integer.parseInt(symbol));
a.setTitle(title);
accessDao.update(a);
return "accessupdate";
}
EDIT: web.xml, spring configuration
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- Context -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/applicationContext.xml,
/WEB-INF/spring/database.xml,
/WEB-INF/spring/spring-security.xml
</param-value>
</context-param>
<!-- Listeners -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Dispatcher Servlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<multipart-config>
<max-file-size>10485760</max-file-size>
<max-request-size>20971520</max-request-size>
<file-size-threshold>5242880</file-size-threshold>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Filters -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p-4.0.xsd" >
<context:component-scan base-package="com.intersections.controller" />
<context:component-scan base-package="com.intersections.model" />
<context:component-scan base-package="com.intersections.dao" />
<mvc:annotation-driven />
<mvc:resources mapping="/assets/**" location="/assets/" />
<mvc:resources mapping="/pdf/**" location="/pdf/" />
</beans>
database.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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.intersections.model.Intersection</value>
<value>com.intersections.model.Access</value>
<value>com.intersections.model.Pole</value>
<value>com.intersections.model.TrafficSignalController</value>
<value>com.intersections.model.Detector</value>
<value>com.intersections.model.SignalHead</value>
<value>com.intersections.model.PedestrianPushButton</value>
<value>com.intersections.model.PedestrianDisplay</value>
<value>com.intersections.model.User</value>
<value>com.intersections.model.Rank</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<bean id="accessDao" class="com.intersections.dao.AccessDao" />
<bean id="detectorDao" class="com.intersections.dao.DetectorDao"/>
<bean id="intersectionDao" class="com.intersections.dao.IntersectionDao" />
<bean id="pedestrianDisplayDao" class="com.intersections.dao.PedestrianDisplayDao"/>
<bean id="pedestrianPushButtonDao" class="com.intersections.dao.PedestrianPushButtonDao"/>
<bean id="poleDao" class="com.intersections.dao.PoleDao"/>
<bean id="signalHeadDao" class="com.intersections.dao.SignalHeadDao"/>
<bean id="trafficSignalControllerDao" class="com.intersections.dao.TrafficSignalControllerDao"/>
<bean id="userDao" class="com.intersections.dao.UserDao" />
<bean id="exportExcel" class="com.intersections.service.ExportExcel" />
</beans>
spring-security.xml
<?xml version='1.0' encoding='UTF-8' ?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="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-4.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd" >
<http pattern="/assets/**" security="none" />
<http auto-config="true">
<access-denied-handler error-page="/403"/>
<intercept-url pattern="/login" access="permitAll()"/>
<intercept-url pattern="/" access="permitAll()"/>
<intercept-url pattern="/pdf/**" access="hasRole('USER')"/>
<intercept-url pattern="/use/**" access="hasRole('USER')"/>
<intercept-url pattern="/insert/**" access="hasRole('FULLUSER')"/>
<intercept-url pattern="/update/**" access="hasRole('FULLUSER')"/>
<form-login login-page="/login"
default-target-url="/" />
<logout />
</http>
<authentication-manager>
<authentication-provider user-service-ref="userDao" />
</authentication-manager>
</beans:beans>
You need to add following in your update method
session.flush();
I am getting this error because of this my application is not able to create a bean for sessionFactory and bean for transactionManager.
nested exception is org.hibernate.MappingException: An AnnotationConfiguration instance is required to use <mapping class="com.entity.Candidate"/>
Here I am sharing my code hope that gives better clarity.
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
metadata-complete="false">
<servlet>
<servlet-name>conceptedge</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<listener>
<listener class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/conceptedge-persistence.xml</param-value>
</context-param>
<servlet-mapping>
<servlet-name>conceptedge</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
sessionFactory bean:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="/WEB-INF/hibernate.cfg.xml"></property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/interview"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
in Dao layer, I am accessing the session as mentioned:
#Autowired
SessionFactory sessionFactory;
#Override
public List<Candidate> getCandidatesList() {
// TODO Auto-generated method stub
Session session = sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(Candidate.class);
return criteria.list();
}
entity class
package com.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
#Entity
public class Candidate {
private int number;
private String name;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#GenericGenerator(name = "system-uuid", strategy = "uuid")
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
servlet.xml:
<context:component-scan base-package="com" >
<context:include-filter type="regex" expression="com.*"/>
</context:component-scan>
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
You have to annotate your class with #Entity and #Table when using
<mapping class="com.entity.Candidate"/>
or else, you need to use sth like
<mapping resource="com/entity/Candidate.hbm.xml" />
and add the equivalent xml mapping file for your entity class.
also dont forget to initialize your sessionFactory with AnnationConfiguration class
new AnnotationConfiguration().configure().buildSessionFactory();
Consider this example in which I have created two JPA entities and used Spring Data JPA repositories to perform simple CRUD -
import java.sql.Timestamp;
import javax.persistence.Version;
#MappedSuperclass
public class AbstractValueObject {
#Id
#GeneratedValue
private Long id;
#Version
#Column(name = "time_stamp")
private Timestamp version;
public Long getId() {
return id;
}
#Override
public String toString() {
if (id == null) {
return "";
}
return id.toString();
}
}
#Entity
#Table(name = "demo")
public class Demo extends AbstractValueObject {
private String name;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "demo")
private List<Owner> owners;
public Demo() {
owners = new ArrayList<>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Owner> getOwners() {
return Collections.unmodifiableList(owners);
}
public void addOwner(Owner owner) {
this.owners.add(owner);
owner.setDemo(this);
}
public void addAllOwners(List<Owner> owners) {
this.owners.addAll(owners);
for (Owner owner : owners) {
owner.setDemo(this);
}
}
public void update(Demo demo) {
this.setName(demo.getName());
this.owners.clear();
this.addAllOwners(demo.getOwners());
}
}
#Entity
#Table(name = "owner")
public class Owner extends AbstractValueObject {
private String attribute;
#ManyToOne(cascade = CascadeType.ALL, optional = false)
#JoinColumn(name = "demo_id", nullable = false)
private Demo demo;
public String getAttribute() {
return attribute;
}
public void setAttribute(String attribute) {
this.attribute = attribute;
}
public Demo getDemo() {
return demo;
}
public void setDemo(Demo demo) {
this.demo = demo;
}
}
After that, I have created a JPA repository for the Demo entity, extending from JpaRepository -
import org.springframework.data.jpa.repository.JpaRepository;
public interface DemoRepository extends JpaRepository<Demo, Long> {}
Corresponding service implementation -
import javax.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
public class DemoServiceImpl implements DemoService {
#Resource
private DemoRepository demoRepository;
#Override
#Transactional
public Demo create(Demo demo) {
return demoRepository.save(demo);
}
#Override
#Transactional
public Demo update(long id, Demo demo) {
Demo dbDemo = demoRepository.findOne(id);
if (dbDemo == null) {
return demo;
}
dbDemo.update(demo);
return dbDemo;
}
#Transactional
public void testRun() {
Owner owner = new Owner();
owner.setAttribute("attribute");
Demo demo = new Demo();
demo.setName("demo");
demo.addOwner(owner);
this.create(demo);
demo.setName("another");
this.update(demo.getId(), demo);
}
}
persistence.xml file -
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
version="2.1">
<persistence-unit name="jpa-optimistic-locking" transaction-type="RESOURCE_LOCAL">
</persistence-unit>
</persistence>
Spring app-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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.keertimaan.example.jpaoptimisticlocking" />
<jpa:repositories base-package="com.keertimaan.example.jpaoptimisticlocking.repository" />
<bean id="demoService" class="com.keertimaan.example.jpaoptimisticlocking.service.DemoServiceImpl" />
<!-- JPA/Database/Transaction Configuration -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test" />
<property name="user" value="root" />
<property name="password" value="admin123" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="2" />
<property name="acquireIncrement" value="1" />
<property name="maxStatements" value="5" />
<property name="idleConnectionTestPeriod" value="500" />
<property name="maxIdleTime" value="1000" />
<property name="loginTimeout" value="800" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="jpa-optimistic-locking" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Now whenever I try to update an entity like this on Windows 7 -
public class App {
public static void main(String[] args) {
DemoService demoService = (DemoService) SpringHelper.INSTANCE.getBean("demoService");
demoService.testRun();
}
}
I get an exception like this -
Exception in thread "main"
org.springframework.orm.ObjectOptimisticLockingFailureException:
Object of class
[com.keertimaan.example.jpaoptimisticlocking.domain.Demo] with
identifier [4]: optimistic locking failed; nested exception is
org.hibernate.StaleObjectStateException: Row was updated or deleted by
another transaction (or unsaved-value mapping was incorrect) :
[com.keertimaan.example.jpaoptimisticlocking.domain.Demo#4] at
org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:228)
at
org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:155)
at
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:519)
at
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
at
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy31.testRun(Unknown Source) at
com.keertimaan.example.jpaoptimisticlocking.App.main(App.java:9)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or
deleted by another transaction (or unsaved-value mapping was
incorrect) :
[com.keertimaan.example.jpaoptimisticlocking.domain.Demo#4] at
org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2541)
at
org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3285)
at
org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
at
org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
at
org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:159)
at
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
at
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at
org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at
org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at
org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
at
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
... 9 more
If I run the same example in Ubuntu, then I get no exception at all and my application completes successfully. Why is that?
I am using Windowsw 7 64-bit edition -
OS Name: Microsoft Windows 7 Enterprise
OS Version: 6.1.7601 Service Pack 1 Build 7601
and my Ubuntu version is 12.04.5 64-bit edition.
JDK used in Windows: jdk7 update 75
JDK used in Ubuntu: jdk7 update 51
MySQL Server version in Windows: 5.6.23-log MySQL Community Server (GPL)
MySQL Server version in Ubuntu: 5.5.41-0ubuntu0.12.04.1 (Ubuntu)
I have a feeling that this is related to the timestamp precision of MySQL 5.6. MySQL 5.6.4 introduced microsecond precision, which will cause a version mismatch, and the locking will fail.
This is not related to your problem directly but in a highly concurrent environment you should not use timestamp as your version as two entity might have the same time! It's better to use a long/int version like below-
#Version
long version;
Also from design perspective please make your super class abstract as well. Can you check if changing these solves your problem?
I'm trying do examples from "Spring in action 3". But have this problem and don't understand why.
I have next classes:
My entity:
package core;
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;
#Entity
#Table(name="users")
public class SplitterImpl{
#Id
#GeneratedValue(generator="increment")
#GenericGenerator(name="increment", strategy="increment")
#Column(name="id")
private int id;
#Column(name="name")
private String name;
#Column(name="password")
private String password;
#Column(name="fullname")
private String fullname;
#Column(name="email")
private String email;
#Column(name="updatebyemail")
private String updatebyemail;
//****************
//public Setters/getters
//****************
}
My DAO:
package core;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository
public class HibernateSplitterDao implements SplitterDAO {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
public void addSplitter(SplitterImpl splitter) {
sessionFactory.getCurrentSession().persist(splitter);
}
}
My main class:
package core;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static String getBean(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("core\\spring.xml");
return ctx.getBean(HibernateSplitterDao.class).toString();
}
}
in xml spring configuration I'm wrote this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="core"></context:component-scan>
<jee:jndi-lookup id="dataSource"
jndi-name="jdbc/splitter"/>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="Splitter"
class="core.SplitterImpl">
<property name="name" value="TGSH"/>
<property name="password" value="ua"/>
<property name="fullname" value="Taras Shevchenko"/>
<property name="email" value="tgsh#gmail.com"/>
<property name="updatebyemail" value="false" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="core"/>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<bean id="dao" class="core.HibernateSplitterDao">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
When I'm trying get some another bean it's all okay. But when I'm trying get HibernateSplitterDao bean, I'm have problem like this:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [core.HibernateSplitterDao] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:318)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)
at core.Main.getBean(Main.java:10)
at org.apache.jsp.index_jsp._jspService(index_jsp.java:68)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
P.S. Sorry for my English.
In Spring xml, refer Impl class instead of the Interface.
<bean id="dao" class="core.HibernateSplitterDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
clean project and run again.
You're trying to get a bean of type SplitterDAO but you haven't defined any of that class. All I see in the splitter is core.SplitterImpl. Try creating a bean that is of type core.SplitterImpl.
<context:annotation-config> is used to enable annotations on beans already registered.(e.g. #Autowired)
<context:component-scan> takes it a step further and scans to register beans within the context. (e.g. #Repository)
Looks like SplitterDao isn't registered (not in xml or not using component-scan)