Skip to content

JDBC Exception while trying to update associations in Many-To-Many Relationship #42

Description

@dipayanb

I have two domain classes:

package com.dipayan

class Author {

    String name
    static hasMany = [books: Book]

    static constraints = {
    }
}

And

package com.dipayan

class Book {

    String name
    int pageCount

    static belongsTo = Author
    static hasMany = [authors: Author]

    static constraints = {
    }
}

and I am using scaffolded controller for both which was generated from gson templates.
After that I inserted 4 authors and 4 books using POST. After the insertion the db content is given below:

mysql> show tables;
+-----------------------+
| Tables_in_person_test |
+-----------------------+
| author                |
| author_books          |
| book                  |
+-----------------------+
3 rows in set (0.00 sec)

mysql> select * from author;
+----+---------+-----------+
| id | version | name      |
+----+---------+-----------+
|  1 |       0 | Author #1 |
|  2 |       0 | Author #2 |
|  3 |       0 | Author #3 |
|  4 |       0 | Author #4 |
+----+---------+-----------+
4 rows in set (0.00 sec)

mysql> select * from book;
+----+---------+---------+------------+
| id | version | name    | page_count |
+----+---------+---------+------------+
|  1 |       0 | Book #1 |        400 |
|  2 |       0 | Book #2 |        400 |
|  3 |       0 | Book #3 |        400 |
|  4 |       0 | Book #4 |        400 |
+----+---------+---------+------------+
4 rows in set (0.00 sec)

After this I tried to create association for one author and three books by doing a PUT request which went through properly.

{
    "id": "1",
    "books" : [
        {"id": 2},
        {"id": 3},
        {"id": 4}
    ]
}

And the DB content is given below after this point.

mysql> select * from author_books;
+---------+-----------+
| book_id | author_id |
+---------+-----------+
|       2 |         1 |
|       3 |         1 |
|       4 |         1 |
+---------+-----------+
3 rows in set (0.00 sec)

Now I tried associating a different Author with the same set of books with a similar PUT request and here the update fails with a JDBC Integrity constraint violation. Below is the given json and the db content after this point.

{
    "id": "2",
    "books" : [
        {"id": 2},
        {"id": 3},
        {"id": 4}
    ]
}
mysql> select * from author_books;
+---------+-----------+
| book_id | author_id |
+---------+-----------+
|       2 |         1 |
|       3 |         1 |
|       4 |         1 |
+---------+-----------+
3 rows in set (0.00 sec)

Error message:

| Error 2013-07-25 22:14:34,990 [http-bio-8080-exec-1] ERROR util.JDBCExceptionReporter  - Duplicate entry '1-3' for key 'PRIMARY'
| Error 2013-07-25 22:14:34,994 [http-bio-8080-exec-1] ERROR events.PatchedDefaultFlushEventListener  - Could not synchronize database state with session
Message: Could not execute JDBC batch update
    Line | Method
->>   61 | update    in com.dipayan.AuthorController
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    195 | doFilter  in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter  in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    724 | run       in java.lang.Thread

Caused by BatchUpdateException: Duplicate entry '1-3' for key 'PRIMARY'
->> 2054 | executeBatchSerially in com.mysql.jdbc.PreparedStatement
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   1467 | executeBatch in     ''
|    297 | executeBatch in org.apache.commons.dbcp.DelegatingStatement
|     61 | update    in com.dipayan.AuthorController
|    195 | doFilter  in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter  in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
^    724 | run . . . in java.lang.Thread

Caused by MySQLIntegrityConstraintViolationException: Duplicate entry '1-3' for key 'PRIMARY'
->>  411 | handleNewInstance in com.mysql.jdbc.Util
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    386 | getInstance in     ''
|   1041 | createSQLException in com.mysql.jdbc.SQLError
|   4187 | checkErrorPacket in com.mysql.jdbc.MysqlIO
|   4119 | checkErrorPacket in     ''
|   2570 | sendCommand in     ''
|   2731 | sqlQueryDirect in     ''
|   2815 | execSQL   in com.mysql.jdbc.ConnectionImpl
|   2155 | executeInternal in com.mysql.jdbc.PreparedStatement
|   2458 | executeUpdate in     ''
|   2006 | executeBatchSerially in     ''
|   1467 | executeBatch in     ''
|    297 | executeBatch in org.apache.commons.dbcp.DelegatingStatement
|     61 | update    in com.dipayan.AuthorController
|    195 | doFilter  in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter  in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
^    724 | run . . . in java.lang.Thread
| Error 2013-07-25 22:14:35,004 [http-bio-8080-exec-1] ERROR errors.GrailsExceptionResolver  - MySQLIntegrityConstraintViolationException occurred when processing request: [PUT] /AuthorTest/api/Author/2
Duplicate entry '1-3' for key 'PRIMARY'. Stacktrace follows:
Message: Duplicate entry '1-3' for key 'PRIMARY'
    Line | Method
->>  411 | handleNewInstance    in com.mysql.jdbc.Util
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    386 | getInstance          in     ''
|   1041 | createSQLException . in com.mysql.jdbc.SQLError
|   4187 | checkErrorPacket     in com.mysql.jdbc.MysqlIO
|   4119 | checkErrorPacket . . in     ''
|   2570 | sendCommand          in     ''
|   2731 | sqlQueryDirect . . . in     ''
|   2815 | execSQL              in com.mysql.jdbc.ConnectionImpl
|   2155 | executeInternal . .  in com.mysql.jdbc.PreparedStatement
|   2458 | executeUpdate        in     ''
|   2006 | executeBatchSerially in     ''
|   1467 | executeBatch         in     ''
|    297 | executeBatch . . . . in org.apache.commons.dbcp.DelegatingStatement
|     61 | update               in com.dipayan.AuthorController
|    195 | doFilter . . . . . . in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter             in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker . . . . .  in java.util.concurrent.ThreadPoolExecutor
|    615 | run                  in java.util.concurrent.ThreadPoolExecutor$Worker
^    724 | run . . . . . . . .  in java.lang.Thread

I am really in a fix as I am using this in production and is unable to understand if I am doing any wrong.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions