I am using spring with hibernate and when I am trying to insert a data which already exists, it throws DataIntegrityViolationException.
So to handle this exception I have placed a try/catch block in my save method in DAO layer, but it's not getting caught.
After that I placed a try/catch block in save method of service layer also but there also its not getting caught.
I have a testMain method in my service layer and when I am handling there its getting caught there.
Please help how to handle this in my DAO layer
public class TestMain {
/**
* #param args
*/
public static void main(String[] args) {
ApplicationContext applicationContext = SpringUtil
.getApplicationContextInstance();
UserDaoService userDaoService = applicationContext.getBean("userDaoService",
UserDaoService.class);
UserDaoImpl userDao = applicationContext.getBean("userDaoImpl",
UserDaoImpl.class);
User user = new User();
user.setActive(true);
user.setEmail("shariquealam01#gmail.com");
user.setFirstName("Md");
user.setMiddleName("Sharique");
user.setLastName("Alam");
user.setId(1);
user.setPassword("123");
user.setUserName("shariquealam01");
userDaoService.saveUser(user);
}
}
#Service
public class UserDaoService {
#Autowired
public UserDao userDao;
#Transactional
public void saveUser(User user){
System.out.println("User Saving");
/*user.setActive(true);
user.setEmail("shariquealam06#gmail.com");
user.setFirstName("Md");
user.setMiddleName("Sharique");
user.setLastName("Alam");
user.setId(6);
user.setPassword("123");
user.setUserName("shariquealam06");*/
userDao.saveUser(user) ;
/*try{
System.out.println("Inside Service Try");
userDao.saveUser(user);
} catch (Exception e){
System.out.println("Exception Occured "+e);
}*/
// deleteUser(3);
}
}
#Repository
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
public Role getRole(int id){
Session session = getSessionFactory().getCurrentSession();
Role role = (Role) session.get(Role.class, id);
return role;
}
#Override
public void saveUser(User user) {
// Session session = getSessionFactory().getCurrentSession();
/*role.setRoleId(102);
role.setRoleName("User");*/
// role.getUsers().add(user);
/*session.save(user);*/
//logger.info( "Executing Query to ADD User"); //Since this query is important for the state of application, have info logging
Role role = getRole(102);
user.getRoles().add(role);
Session session = sessionFactory.getCurrentSession();
session.save( user );
//userId = user.getId();
//logger.info( "User ADDED to DB with userId as {}", user.getId() );
//session.save(role);
}
}
Exception in thread "main" org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:163)
at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:730)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:592)
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:515)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at com.sharique.service.UserDaoService$$EnhancerBySpringCGLIB$$956522ab.saveUser(<generated>)
at com.sharique.main.TestMain.main(TestMain.java:40)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3124)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
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.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
... 9 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Violation of PRIMARY KEY constraint 'PK__USER_DET__F3BEEBFF77DFC722'. Cannot insert duplicate key in object 'dbo.USER_DETAILS'.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:314)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
... 22 more
The exception, as the stack trace should show, doesn't happen when you call persist() or save(). It happens when flush() is called, i.e. when the SQL insert statements are actually executed. And flush() is called automatically just before the transaction commits.
You could call flush() explicitely and catch the exception, but that would be useless, because Hibernate exceptions are irrecoverable. They leave the session in an unusable state. The only safe thing to do when facing such an exception is to rolback the transaction and close the session.
So do the right thing: use autogenerated primary keys and/or check that the data doesn't exist, using a query, before trying to insert it.
Related
We have multi-schema DB, and each schema contains algorithm_execution table First I get the schema-list, and then prepare the update query for one-by-one in loop for each schema-name and run EntityManager.executeUpdate() which is failing with below error. Not sure what is the root cause as table exists in schema and I am able to run same update query on table using pgsql client.
Edit:
Tried to query/update the entity using spring data repository as well but that also fails. Can't we query a table on each schema one-by-one in for loop, before running the query we are specifying the schema in the context.
The method that is failing -
Code:
private void updateJobStatus(EntityManager entityManager, String schemaName, AlgorithmExecution execution) throws Exception{
try {
private static final String UPDATE_JOB_STATUS_QUERY =
String updateQuery = "UPDATE "+schemaName+".algorithm_execution SET job_status = :job_status, modification_time = :modification_time, error_message = :error_message, job_logs = :job_logs WHERE id = :id";
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.createNativeQuery(updateQuery)
.setParameter("job_status", execution.getJobStatus())
.setParameter("modification_time", execution.getModifiedTime())
.setParameter("error_message", execution.getErrorMessage())
.setParameter("job_logs", execution.getJobLogs())
.setParameter("id", execution.getId())
.executeUpdate();
transaction.commit();
} catch ( Exception ex) {
LOGGER.warn("An exception occured during updateJobStatus, error {}", ex.getMessage());
LOGGER.debug("An exception occured during updateJobStatus",ex);
throw new Exception("An exception occured during updateJobStatus", ex);
}
}
Hibernate internal logs below update query in the logs:
2020-12-15 12:11:28.159 +0000 [main] [DEBUG] - org.hibernate.SQL [org.hibernate.engine.jdbc.spi.SqlStatementLogger:logStatement:128] - update algorithm_execution set algorithm_checksum=?, algorithm_id=?, create_time=?, error_message=?, job_logs=?, job_name=?, job_status=?, job_summary=?, job_type=?, modification_time=?, next_execution=?, owner=?, previous_execution=?, start_time=?, tenant_id=? where id=?
Below is the exception stack trace -
Exception:
ava.lang.Exception: An exception occured during updateJobStatus
at com.bmc.aif.jobmanager.jobmanagement.AIFJobManagementTask.updateJobStatus(AIFJobManagementTask.java:144)
at com.bmc.aif.jobmanager.jobmanagement.AIFJobManagementTask.jobStatusFailedOrUnknown(AIFJobManagementTask.java:118)
at com.bmc.aif.jobmanager.jobmanagement.AIFJobManagementTask.executeTasks(AIFJobManagementTask.java:79)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:895)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at com.bmc.aif.jobmanager.jobmanagement.AIFJobManagementTask.main(AIFJobManagementTask.java:149)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1356)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1339)
at org.hibernate.query.internal.NativeQueryImpl.beforeQuery(NativeQueryImpl.java:264)
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1610)
at com.bmc.aif.jobmanager.jobmanagement.AIFJobManagementTask.updateJobStatus(AIFJobManagementTask.java:139)
... 25 common frames omitted
Caused by: org.hibernate.exception.SQLGrammarException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:103)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3430)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3292)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3704)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:201)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1352)
... 29 common frames omitted
Caused by: org.postgresql.util.PSQLException: ERROR: relation "algorithm_execution" does not exist
Position: 8
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2532)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2267)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:312)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:448)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:369)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:153)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:119)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 41 common frames omitted
Hi,
I am able to fix above issue using CrudRepository like -
#Repository
public interface AlgorithmExecutionRepository extends CrudRepository<AlgorithmExecution, UUID>
#Autowired
AlgorithmExecutionRepository executionRepository;
private void updateJobStatus(AlgorithmExecution execution)
throws Exception {
try {
LOGGER.info("Set the RequestContext, the current tenant is {}", RequestContext.getCurrentTenant());
LOGGER.info("updating the execution {} for jobId {} for status {} of tenant {}",
execution.getId(),execution.getAlgorithmId(), execution.getJobStatus(), execution.getTenantId());
executionRepository.save(execution);
LOGGER.info("Syccessfully updated the execution {} for jobId {} for status {} of tenant {}",
execution.getId(),execution.getAlgorithmId(), execution.getJobStatus(), execution.getTenantId());
} catch (Exception ex) {
LOGGER.warn("An exception occured during updateJobStatus, error {}", ex.getMessage());
LOGGER.debug("An exception occured during updateJobStatus", ex);
throw new Exception("An exception occured during updateJobStatus", ex);
}finally {
RequestContext.clear();
LOGGER.info("Cleared the RequestContext, the current tenant is {}", RequestContext.getCurrentTenant());
}
}
Also, extended MultiTenantConnectionProvider to override the hibernate connection method. Need to set the schema and get the connection to that schema and then update the table.
#Component
public class TenantConnectionProvider implements MultiTenantConnectionProvider {
#Override
public void releaseAnyConnection(Connection connection) throws SQLException {
connection.close();
}
#Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
logger.info("Get connection for tenant {}", tenantIdentifier);
final Connection connection = getAnyConnection();
connection.setSchema(Constants.SCHEMA_PREFIX + "_" +tenantIdentifier.toUpperCase().trim());
return connection;
}
#Override
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
logger.info("Release connection for tenant {}", tenantIdentifier);
releaseAnyConnection(connection);
}
}
The code works fine but as I tried to add commit command the code start giving exception. Any suggestion will be helpful.
The line transaction.commit(); is causing problem.
public class MovieDAO
{
/**
* Adds an movie record to database from the given {#link Movie}
* Displays a success message upon successful execution
* #param movie
* #throws Exception
*/
public void addMovie(Movie movie) throws Exception
{
EntityManagerFactory factory = null;
EntityManager manager = null;
MovieEntity movieobj = null;
try
{
factory = Persistence.createEntityManagerFactory("Demo");
manager = factory.createEntityManager();
movieobj = new MovieEntity();
movieobj.setLanguage(movie.getLanguage());
movieobj.setMovieId(movie.getMovieId());
movieobj.setMovieName(movie.getMovieName());
movieobj.setReleasedIn(movie.getReleasedIn());
movieobj.setRevenueInDollars(movie.getRevenueInDollars());
EntityTransaction transaction = manager.getTransaction();
transaction.begin();
manager.persist(movieobj);
transaction.commit();
}
catch(Exception e)
{
DOMConfigurator.configure("src/resources/log4j.xml");
Logger logger = Logger.getLogger(this.getClass());
logger.error(e.getMessage(), e);
//throw new Exception("DAO.TECHNICAL_ERROR");
e.printStackTrace();
}
finally
{
if(manager != null)
manager.close();
if(factory != null)
factory.close();
}
}
}
The error I am getting is:
javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:94)
at dao.MovieDAO.addMovie(MovieDAO.java:44)
at ui.UserInterface.addMovie(UserInterface.java:23)
at ui.UserInterface.main(UserInterface.java:39)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute statement
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:82)
... 3 more
Caused by: org.hibernate.exception.SQLGrammarException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:80)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3124)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
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:1258)
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)
... 3 more
Caused by: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:943)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1150)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:4875)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1361)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
... 16 more
Seems like you are missing a table:
ORA-00942: table or view does not exist
Check the declared table for your entity and verify if this table exists in your Oracle database.
I want to get serial numbers with the help of database.
Here is what I want:
1.read the entity from database and lock it
2.increase the serial number and upadte the entity.
I am asuming the first thread can lock the record and the other thread won't work until the first thread commits its transaction, however, I got the opposite of what I want.
below is my code:
Repository:
public interface ActivityNoGeneratorRepository extends BaseRepository<ActivityNoGenerator, Long> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
#Query(value = "select generator from ActivityNoGenerator generator where id=:id")
ActivityNoGenerator getGeneratorByIdForUpdate(#Param("id") Long id);
}
Service:
#Service
public class ActivityNoGeneratorServiceImpl implements IActivityNoGeneratorService {
#Autowired
private ActivityNoGeneratorRepository activityNoGeneratorRepository;
#Override
#Transactional
public String getActivityNo() {
ActivityNoGenerator activityNoGenerator = activityNoGeneratorRepository.getGeneratorByIdForUpdate(1L);
System.out.println(1);
Integer currentValue = activityNoGenerator.getCurrentValue() + 1;
if (!StringUtils.equals(DateFormatUtils.format(new Date(), "yyyyMM"), DateFormatUtils.format(activityNoGenerator.getLastAccessTime(), "yyyyMM"))) {
currentValue = 1;
}
String serialNum = String.format("%0" + activityNoGenerator.getWidth() + "d", currentValue);
String activityNo = activityNoGenerator.getPrefix() + activityNoGenerator.getPlatformCode() + DateFormatUtils.format(new Date(), "yyyyMM") + serialNum;
activityNoGenerator.setCurrentValue(currentValue);
activityNoGenerator.setLastAccessTime(new Date());
activityNoGeneratorRepository.save(activityNoGenerator);
return activityNo;
}
}
Test:
public class IActivityNoGeneratorServiceTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath*:spring/applicationContext.xml");
final IActivityNoGeneratorService activityNoGeneratorService = applicationContext.getBean(IActivityNoGeneratorService.class);
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
#Override
public void run() {
System.out.println(activityNoGeneratorService.getActivityNo());
}
}).start();
}
}
}
Result:
Hibernate:
select
activityno0_.id as id1_3_,
activityno0_.current_value as current_2_3_,
activityno0_.last_access_time as last_acc3_3_,
activityno0_.platform_code as platform4_3_,
activityno0_.platform_name as platform5_3_,
activityno0_.prefix as prefix6_3_,
activityno0_.step as step7_3_,
activityno0_.width as width8_3_
from
activity_no_generator activityno0_
where
activityno0_.id=? for update
Hibernate:
select
activityno0_.id as id1_3_,
activityno0_.current_value as current_2_3_,
activityno0_.last_access_time as last_acc3_3_,
activityno0_.platform_code as platform4_3_,
activityno0_.platform_name as platform5_3_,
activityno0_.prefix as prefix6_3_,
activityno0_.step as step7_3_,
activityno0_.width as width8_3_
from
activity_no_generator activityno0_
where
activityno0_.id=? for update
1
1
Hibernate:
update
activity_no_generator
set
current_value=?,
last_access_time=?,
platform_code=?,
platform_name=?,
prefix=?,
step=?,
width=?
where
id=?
Hibernate:
update
activity_no_generator
set
current_value=?,
last_access_time=?,
platform_code=?,
platform_name=?,
prefix=?,
step=?,
width=?
where
id=?
Exception in thread "Thread-6" org.springframework.orm.jpa.JpaSystemException: commit failed; nested exception is org.hibernate.TransactionException: commit failed
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:333)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:483)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:290)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy44.getActivityNo(Unknown Source)
at com.lemall.srd.pop.activity.oa.service.IActivityNoGeneratorServiceTest$1.run(IActivityNoGeneratorServiceTest.java:18)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.TransactionException: commit failed
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:187)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
... 10 more
Caused by: org.hibernate.TransactionException: unable to commit against JDBC connection
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:116)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:180)
... 12 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.Util.getInstance(Util.java:387)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:950)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3966)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3902)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2526)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2673)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545)
at com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1614)
at com.zaxxer.hikari.pool.ProxyConnection.commit(ProxyConnection.java:355)
at com.zaxxer.hikari.pool.HikariProxyConnection.commit(HikariProxyConnection.java)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:112)
... 13 more
HD1020012017050631
Process finished with exit code 0
I debug my code and find the second thread executed without waiting the first thread commit.
Any clue what mistake I make? Thanks very much!
What I see is that you are missing the #Transactional annotation in your repository method which might be the reason that your service method and repo method are running in two different transactions. Also use the Propagation.Required option in your transactional annotation.
I am getting run time error in Play Framework 2.5 (Java) :
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[CompletionException: java.lang.IllegalStateException: Tried to remove the Entit yManager, but none was set.]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:280)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:206)
at play.api.GlobalSettings$class.onError(GlobalSettings.scala:160)
at play.api.DefaultGlobal$.onError(GlobalSettings.scala:188)
at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:98)
at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100)
at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
Caused by: java.util.concurrent.CompletionException: java.lang.IllegalStateException: Tried to remove the EntityManager, but none was set.
at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:593)
at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577)
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1977)
at scala.concurrent.java8.FuturesConvertersImpl$CF.apply(FutureConvertersImpl.scala:21)
at scala.concurrent.java8.FuturesConvertersImpl$CF.apply(FutureConvertersImpl.scala:18)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:63)
Caused by: java.lang.IllegalStateException: Tried to remove the EntityManager, but none was set.
at play.db.jpa.JPAEntityManagerContext.pop(JPAEntityManagerContext.java:74)
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:155)
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:195)
at play.db.jpa.TransactionalAction.call(TransactionalAction.java:25)
at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:108)
at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:108)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:56)
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
Below is the code :
#Transactional
public Result logincheck(){
Form<User> loginForm = Form.form(User.class).bindFromRequest();
User user = loginForm.get();
User searchUser = UserDao.findUser(user);
if (searchUser != null){
return ok(homepage.render());
}
return ok(login.render(loginForm));
}
In class UserDao:
public static User findUser(User user){
EntityManager em = jpaApi.em();
TypedQuery<User> query = JPA.em().createQuery("select u.* from [RL].[dbo].[userdetails] u where u.userid = :username and u.password = :password", User.class);
query.setParameter("username", user.userid);
query.setParameter("password", user.password);
try{
return (User) query.getSingleResult();
} catch(NoResultException e){
return null;
}
}
We found this issue while working with play2.5. We fixed it by adding
the persistence.xml file into the project as specified here : Play 2.5 JavaJPA creating a persistence unit
and adding the following in the application.conf:
jpa.default=defaultPersistenceUnit
You are using JPA.em() and jpaApi in the same method. Actually this should be the same entity manager. Starting from play 2.5 the proper way is jpaApi, JPA.em() is deprecated. You should take care to inject jpaApi.
The code may be like this:
public static User findUser(User user) {
JPAApi jpaApi = Play.current().injector().instanceOf(JPAApi.class);
EntityManager em = jpaApi.em();
TypedQuery<User> query = em.createQuery("select u.* from [RL].[dbo].[userdetails] u where u.userid = :username and u.password = :password", User.class);
...
}
You can read more here about dependency injection in Play
I have this #NamedNativeQuery
#NamedNativeQuery(name = "Certificacion.updateCertificacionAclaraciones", query = "UPDATE CERTIFICACION "
+ "SET PENDIENTE_GENERACION = :pendienteGeneracion, ID_ACLARACIONES_TEMP_ESCRITO = :idAclaracion "
+ "WHERE ID IN (:paso)")
And I have this EJB structure to get a transaction
#TransactionManagement(TransactionManagementType.CONTAINER)
#Stateless
public class PRequerimientoCCServiceBean implements
IPRequerimientoCCServiceBeanLocal {
#Override
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void guardarRequerimiento(Usuario usuario,
ConjuntoCertificaciones conjunto, String aclaracionGeneral,
Map<Long, String> mapAclaracionColegio) throws RollbackException {
try {
// Realizamos el guardado de las aclaraciones y la generaciĆ³n del
// documento
AclaracionesTempEscrito currentAclaracion = new AclaracionesTempEscrito();
...
entityManager.persist(currentAclaracion);
generarDocumento(currentAclaracion, conjunto, usuario);
} catch (Exception e) {
ejbContext.setRollbackOnly();
throw new RollbackSajgException();
}
}
#TransactionAttribute(TransactionAttributeType.MANDATORY)
private void generarDocumento(AclaracionesTempEscrito findAclaracion,
ConjuntoCertificaciones conjunto, Usuario usuario)
throws RollbackException {
...
Query actualizaCertificacionesAclaracion = entityManager
.createNamedQuery("Certificacion.updateCertificacionAclaraciones");
actualizaCertificacionesAclaracion
.setParameter("pendienteGeneracion", true)
.setParameter("idAclaracion", findAclaracion.getId())
.setParameter("paso", paso).executeUpdate();
}
}
It suppose that I will execute commit when guardarRequerimiento method ends but when I execute my nativeQuery with executeUpdate I get an exception of ConstraintViolation
org.hibernate.exception.ConstraintViolationException: could not
execute statement
I think that it is because although findAclaracion.getId() exists in the transaction, it does not exist in database and the executeUpdate need that this object exist in database because is not in my persistence context when execute.
Why do I get this behaviour? How can I solve?
Thank you.
You can try to refresh this object after flush and before generarDocumento(currentAclaracion, conjunto, usuario);
or
you can do it as query and loop that objectList updating values..