looks like the mysql duplicate entry exception is not be caught?

124 views
Skip to first unread message

吴冉波

unread,
Oct 29, 2016, 4:47:06 AM10/29/16
to ScalikeJDBC Users Group
the exception 'com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry ' looks not be catched and not be auto rollback. 


My code looks like this

Future {
DB localTx { implicit session =>
   sqls"insert into TA(a) VALUES(a)".apply
   sqls"insert into TB(b) VALUES(b)".apply
}
}recover {
  case e: Exception =>
      e.printStack()
}

when I got the final printStack, but the "Insert into TA" is commit to database. It should be rollback. 


Then I read some scalikejdbc code and change it to 

Future {
DB localTx { implicit session =>
  try {
     sqls"insert into TA(a) VALUES(a)".apply
     sqls"insert into TB(b) VALUES(b)".apply
  } catch {
    case e: Exception => 
        print("manually handle exception")
        throw e
  }
}
}recover {
  case e: Exception =>
      e.printStack()
}

the "manually handle exception" is not be catched.




the origin stack:
[SQL Execution] insert into Role (name, memo, domain_id, created_time, updated_time) values ('test_zhai12', 'xe6xb5x8bxe8xafx95xe7xbfx9f', 1, null, null); (2 ms)      /// this insert is commited to database.I thought it  shoule be rollback.
[SQL Execution] select distinct permission.id as i_on_permission from Permission permission inner join Role_Permission role_permission on permission.id = role_permission.permission_id where role_permission.role_id = 94; (3 ms)
[SQL Execution] delete from Permission where FALSE; (1 ms)
[SQL Execution] insert into Permission (permission_meta_id, resource_id) values (118, null); (3 ms)   // be commited
[SQL Execution] insert into Role_Permission (permission_id, role_id) values (305, 94); (2 ms) // be commited
[SQL Execution Failed] insert into Permission (permission_meta_id, resource_id) values (115, 67) (Reason: Duplicate entry '115-67' for key 'permission_permission_meta_resource_uniq')
[Rizhiyi]: error Stack Trace from frontend
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '115-67' for key 'permission_permission_meta_resource_uniq'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
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:932)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5094)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at scalikejdbc.StatementExecutor$$anonfun$executeUpdate$1.apply$mcI$sp(StatementExecutor.scala:329)
at scalikejdbc.StatementExecutor$$anonfun$executeUpdate$1.apply(StatementExecutor.scala:329)
at scalikejdbc.StatementExecutor$$anonfun$executeUpdate$1.apply(StatementExecutor.scala:329)
at scalikejdbc.StatementExecutor$NakedExecutor.apply(StatementExecutor.scala:18)
at scalikejdbc.StatementExecutor$$anon$1.scalikejdbc$StatementExecutor$LoggingSQLAndTiming$$super$apply(StatementExecutor.scala:309)
at scalikejdbc.StatementExecutor$LoggingSQLAndTiming$class.apply(StatementExecutor.scala:253)
at scalikejdbc.StatementExecutor$$anon$1.scalikejdbc$StatementExecutor$LoggingSQLIfFailed$$super$apply(StatementExecutor.scala:309)
at scalikejdbc.StatementExecutor$LoggingSQLIfFailed$class.apply(StatementExecutor.scala:286)
at scalikejdbc.StatementExecutor$$anon$1.apply(StatementExecutor.scala:309)
at scalikejdbc.StatementExecutor.executeUpdate(StatementExecutor.scala:329)
at scalikejdbc.DBSession$$anonfun$updateWithFilters$1.apply(DBSession.scala:432)
at scalikejdbc.DBSession$$anonfun$updateWithFilters$1.apply(DBSession.scala:430)
at scalikejdbc.LoanPattern$class.using(LoanPattern.scala:18)
at scalikejdbc.ActiveSession.scalikejdbc$DBSession$$super$using(DBSession.scala:586)
at scalikejdbc.DBSession$class.using(DBSession.scala:30)
at scalikejdbc.ActiveSession.using(DBSession.scala:586)
at scalikejdbc.DBSession$class.updateWithFilters(DBSession.scala:429)
at scalikejdbc.ActiveSession.updateWithFilters(DBSession.scala:586)
at scalikejdbc.DBSession$class.updateAndReturnSpecifiedGeneratedKey(DBSession.scala:516)
at scalikejdbc.ActiveSession.updateAndReturnSpecifiedGeneratedKey(DBSession.scala:586)
at scalikejdbc.SQLUpdateWithGeneratedKey$$anonfun$9.apply(SQL.scala:549)
at scalikejdbc.SQLUpdateWithGeneratedKey$$anonfun$9.apply(SQL.scala:549)
at scalikejdbc.SQLUpdateWithGeneratedKey.apply(SQL.scala:556)
at cn.yottabyte.mysql.Permission$.create(Permission.scala:108)
at cn.yottabyte.mysql.Role$.assignPermission(Role.scala:71)
at cn.yottabyte.privilege.permit.RoleBuilder$$anonfun$commitPermissions$2.apply(RoleBuilder.scala:193)
at cn.yottabyte.privilege.permit.RoleBuilder$$anonfun$commitPermissions$2.apply(RoleBuilder.scala:191)
at scala.collection.immutable.List.foreach(List.scala:318)
at cn.yottabyte.privilege.permit.RoleBuilder.commitPermissions(RoleBuilder.scala:191)
at cn.yottabyte.privilege.permit.RoleBuilder.commit(RoleBuilder.scala:170)
at cn.yottabyte.db_handlers.PrivilegeHandler.doCreateRole(PrivilegeHandler.scala:83)
at cn.yottabyte.db_handlers.PrivilegeHandler$$anonfun$2.apply(PrivilegeHandler.scala:36)
at cn.yottabyte.db_handlers.PrivilegeHandler$$anonfun$2.apply(PrivilegeHandler.scala:36)
at cn.yottabyte.Handler.handleRequest(Handler.scala:47)
at cn.yottabyte.FrontendService$$anonfun$cn$yottabyte$FrontendService$$handleHttpRequest$2$$anonfun$1.apply(FrontendService.scala:49)
at cn.yottabyte.FrontendService$$anonfun$cn$yottabyte$FrontendService$$handleHttpRequest$2$$anonfun$1.apply(FrontendService.scala:45)
at scalikejdbc.DBConnection$$anonfun$3.apply(DBConnection.scala:305)
at scalikejdbc.DBConnection$class.scalikejdbc$DBConnection$$rollbackIfThrowable(DBConnection.scala:274)
at scalikejdbc.DBConnection$class.localTx(DBConnection.scala:303)
at scalikejdbc.DB.localTx(DB.scala:60)
at scalikejdbc.DB$.localTx(DB.scala:257)
at cn.yottabyte.FrontendService$$anonfun$cn$yottabyte$FrontendService$$handleHttpRequest$2.apply$mcV$sp(FrontendService.scala:45)
at cn.yottabyte.FrontendService$$anonfun$cn$yottabyte$FrontendService$$handleHttpRequest$2.apply(FrontendService.scala:38)
at cn.yottabyte.FrontendService$$anonfun$cn$yottabyte$FrontendService$$handleHttpRequest$2.apply(FrontendService.scala:38)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)


version:
"org.scalikejdbc" %% "scalikejdbc"       % "2.3.4",
"org.scalikejdbc" %% "scalikejdbc-config" % "2.3.4",
"org.scalikejdbc" %% "scalikejdbc-test" % "2.3.4" % "test",


吴冉波

unread,
Oct 29, 2016, 5:03:44 AM10/29/16
to ScalikeJDBC Users Group

the only way I can see the rollback run is: I change the code to some like this.


Future {
DB localTx { implicit session =>
  try {
     sqls"insert into TA(a) VALUES(a)".apply
     sqls"insert into TB(b) VALUES(b)".apply
  } catch {
    case e: Exception => 
        print("manually handle exception")
        throw e
  } finally {
    session.close()
  }
}
}recover {
  case e: Exception =>
      println("finally-s")
      e.printStack()
      println("finally-e")
}

I close the session, it is wrong( I know), but then, I got see the rollback method is called in the StackTrace. And I find the 


// these a rollbacked this time.
[SQL Execution] insert into Role (name, memo, domain_id, created_time, updated_time) values ('test_zhai13', 'xe6xb5x8bxe8xafx95xe7xbfx9f', 1, null, null); (2 ms)
[SQL Execution] select distinct permission.id as i_on_permission from Permission permission inner join Role_Permission role_permission on permission.id = role_permission.permission_id where role_permission.role_id = 95; (2 ms)
[SQL Execution] delete from Permission where FALSE; (2 ms)
[SQL Execution] insert into Permission (permission_meta_id, resource_id) values (118, null); (2 ms)
[SQL Execution] insert into Role_Permission (permission_id, role_id) values (307, 95); (10 ms)
[SQL Execution Failed] insert into Permission (permission_meta_id, resource_id) values (115, 67) (Reason: Duplicate entry '115-67' for key 'permission_permission_meta_resource_uniq')
[日志易]: error Stack Trace from frontend
at scalikejdbc.DBConnection$class.scalikejdbc$DBConnection$$rollbackIfThrowable(DBConnection.scala:274)     // the method is called as before, and the rollback part is not called as before. See the log below, I found the rollback part is called.
at scalikejdbc.DBConnection$class.localTx(DBConnection.scala:303)
at scalikejdbc.DB.localTx(DB.scala:60)
at scalikejdbc.DB$.localTx(DB.scala:257)
at cn.yottabyte.FrontendService$$anonfun$cn$yottabyte$FrontendService$$handleHttpRequest$2.apply$mcV$sp(FrontendService.scala:45)
at cn.yottabyte.FrontendService$$anonfun$cn$yottabyte$FrontendService$$handleHttpRequest$2.apply(FrontendService.scala:38)
at cn.yottabyte.FrontendService$$anonfun$cn$yottabyte$FrontendService$$handleHttpRequest$2.apply(FrontendService.scala:38)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

-------finally---s---------finally---s---------finally---s---------finally---s---------finally---s---------finally---s---------finally---s---------finally---s---------finally---s---------finally---s--A Connection is closed.
-------finally---e---------finally---e---------finally---e---------finally---e---------finally---e---------finally---e---------finally---e---------finally---e---------finally---e---------finally---e--Could not successfully complete local transaction
java.lang.IllegalStateException: Transaction is not active. If you want to start a new transaction, use #newTx instead.
at scalikejdbc.DBConnection$$anonfun$tx$1.apply(DBConnection.scala:125)
at scalikejdbc.DBConnection$$anonfun$tx$1.apply(DBConnection.scala:124)
at scala.util.control.Exception$Catch$$anon$2.apply(Exception.scala:136)
at scala.util.control.Exception$Catch$$anon$2.apply(Exception.scala:134)
at scala.util.control.Exception$Catch.apply(Exception.scala:105)
at scalikejdbc.DBConnection$class.tx(DBConnection.scala:128)
at scalikejdbc.DB.tx(DB.scala:60)
at scalikejdbc.DBConnection$class.scalikejdbc$DBConnection$$rollbackIfThrowable(DBConnection.scala:281)      // see rollback is called

吴冉波

unread,
Oct 29, 2016, 5:27:51 AM10/29/16
to ScalikeJDBC Users Group
I thinks it is because the Future, I run the similar code in sbt console. And the rollback work fine. 
I will try run the exacted same code only without Future, to checkout finally.


scala> DB localTx { implicit session => sql"""insert into Role(name, memo, domain_id) VALUES("testuseless2", "useless", 1)""".execute.apply() || sql"insert into Role_Permission (permission_id, role_id) values (307, 95)".execute().apply() }
[SQL Execution] insert into Role(name, memo, domain_id) VALUES("testuseless2", "useless", 1); (2 ms)
[SQL Execution Failed] insert into Role_Permission (permission_id, role_id) values (307, 95) (Reason: Cannot add or update a child row: a foreign key constraint fails (`rizhiyi_system`.`Role_Permission`, CONSTRAINT `fk_role_permission_role_id` FOREIGN KEY (`role_id`) REFERENCES `Role` (`id`) ON DELETE CASCADE))
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`rizhiyi_system`.`Role_Permission`, CONSTRAINT `fk_role_permission_role_id` FOREIGN KEY (`role_id`) REFERENCES `Role` (`id`) ON DELETE CASCADE)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
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:932)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1192)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:198)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:198)
at scalikejdbc.StatementExecutor$$anonfun$execute$1.apply$mcZ$sp(StatementExecutor.scala:313)
at scalikejdbc.StatementExecutor$$anonfun$execute$1.apply(StatementExecutor.scala:313)
at scalikejdbc.StatementExecutor$$anonfun$execute$1.apply(StatementExecutor.scala:313)
at scalikejdbc.StatementExecutor$NakedExecutor.apply(StatementExecutor.scala:18)
at scalikejdbc.StatementExecutor$$anon$1.scalikejdbc$StatementExecutor$LoggingSQLAndTiming$$super$apply(StatementExecutor.scala:309)
at scalikejdbc.StatementExecutor$LoggingSQLAndTiming$class.apply(StatementExecutor.scala:253)
at scalikejdbc.StatementExecutor$$anon$1.scalikejdbc$StatementExecutor$LoggingSQLIfFailed$$super$apply(StatementExecutor.scala:309)
at scalikejdbc.StatementExecutor$LoggingSQLIfFailed$class.apply(StatementExecutor.scala:286)
at scalikejdbc.StatementExecutor$$anon$1.apply(StatementExecutor.scala:309)
at scalikejdbc.StatementExecutor.execute(StatementExecutor.scala:313)
at scalikejdbc.DBSession$$anonfun$executeWithFilters$1.apply(DBSession.scala:366)
at scalikejdbc.DBSession$$anonfun$executeWithFilters$1.apply(DBSession.scala:364)
at scalikejdbc.LoanPattern$class.using(LoanPattern.scala:18)
at scalikejdbc.ActiveSession.scalikejdbc$DBSession$$super$using(DBSession.scala:586)
at scalikejdbc.DBSession$class.using(DBSession.scala:30)
at scalikejdbc.ActiveSession.using(DBSession.scala:586)
at scalikejdbc.DBSession$class.executeWithFilters(DBSession.scala:363)
at scalikejdbc.ActiveSession.executeWithFilters(DBSession.scala:586)
at scalikejdbc.SQLExecution$$anonfun$6.apply(SQL.scala:501)
at scalikejdbc.SQLExecution$$anonfun$6.apply(SQL.scala:501)
at scalikejdbc.SQLExecution.apply(SQL.scala:508)
at $anonfun$1.apply(<console>:12)
at $anonfun$1.apply(<console>:12)
at scalikejdbc.DBConnection$$anonfun$3.apply(DBConnection.scala:305)
at scalikejdbc.DBConnection$class.scalikejdbc$DBConnection$$rollbackIfThrowable(DBConnection.scala:274)
at scalikejdbc.DBConnection$class.localTx(DBConnection.scala:303)
at scalikejdbc.DB.localTx(DB.scala:60)
at scalikejdbc.DB$.localTx(DB.scala:257)
at .<init>(<console>:12)
at .<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at $print(<console>)
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 scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983)
at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568)
at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:760)
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:805)
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:717)
at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:581)
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:588)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:591)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:882)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837)
at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:837)
at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:904)
at xsbt.ConsoleInterface.run(ConsoleInterface.scala:69)
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 sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:102)
at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:77)
at sbt.Console.sbt$Console$$console0$1(Console.scala:23)
at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:24)
at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply(Console.scala:24)
at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply(Console.scala:24)
at sbt.Logger$$anon$4.apply(Logger.scala:90)
at sbt.TrapExit$App.run(TrapExit.scala:244)
at java.lang.Thread.run(Thread.java:745)

Kazuhiro Sera

unread,
Nov 5, 2016, 1:42:53 AM11/5/16
to 吴冉波, ScalikeJDBC Users Group
Any updates? If you share us a minimal working example, we may be able
to help you.

-Kaz
> --
> You received this message because you are subscribed to the Google Groups
> "ScalikeJDBC Users Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to scalikejdbc-users...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

吴冉波

unread,
Nov 6, 2016, 12:36:26 AM11/6/16
to ScalikeJDBC Users Group, wur...@gmail.com
busy week. my bad.

Scalikejdbc is right. It's my code's wrong.

I caught a Exception and not throw it. It works good with my old code, it make me think it may be the Future and DB transaction caused, my wrong.

Thank you!
Reply all
Reply to author
Forward
0 new messages