aspose file tools*
The moose likes Object Relational Mapping and the fly likes RollbackException thrown when adding ManyToOne relationship Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "RollbackException thrown when adding ManyToOne relationship" Watch "RollbackException thrown when adding ManyToOne relationship" New topic
Author

RollbackException thrown when adding ManyToOne relationship

Luca Tampellini
Greenhorn

Joined: Apr 28, 2014
Posts: 3
Scenario: I have a JSF 2.1 webapp running on a tomcat server, with hibernate implementing the jpa interface and mysql database.
Users of the webapp are registered as an Entity on the database, and there are a group of data called Rooms, that have their own Entity, where users have access as proprietary or as external managers. To save the concept of "external management" on the database i have a proper Entity for every management; the external management are saved as a OneToMany relathionship on the User Entity.

Problem: For some odd reason, adding the code for a foreign key to the managed room in the External Management Entity with a ManyToOne relationship, breaks up Hibernate: any update to the list of external management property on the User, when that foreign key is present, throws RollbackException - "Transaction marked as rollback only":


As you probably know, the sad thing about those RollbackException in Hibernate is that they are UNDEBUGGABLE!

CODE
the User entity:



The External Management Entity


I will not post the Room Entity code, as it is not so important.

and this is the piece of code where the user with a set of external managements is updated on the database and the exception is thrown:


The last two lines are the critical step: if the External Management Entity has that "criminal code" about the ManyToOne relationship to the managed room, the userDao.update(...) will throw the exception; if the "criminal code" is omitted, the userDao.update(...) will NOT throw the exception.

(The room has already been previously persisted to the database before i use it in that last code segment)

Question: sadly i need that ManyToOne relationship to the managed room, do you know why it breaks the persistence up?

Post-Scriptum: i tried to change the ManyToOne relationship to a OneToOne but it had no effect.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16145
    
  21

Welcome to the JavaRanch, Luca!

Aren't you missing something from that stacktrace? When I get a Hibernate JPA rollback exception, it's chained to the exception that initiated the rollback.

I'm sure I've missed some details. It's hard to follow stuff that's too big to be seen all at once on the same screen, but I understand that you are committing the parent and child in separate operations. You would be better off doing them both in a single transaction.

In the case of a one-to-many transaction, if you have the correct options set on your entity definitions, committing the parent will automatically commit the child objects. You do need to have the parent and child relationships properly set in your object model when you do this, though. Also, when updating parent-child sets where children may be removed as well as added, JPA2 added an "orphanRemoval" option to get around the case where the in-memory database model gets out of sync with the actual database because removed objects are not by default disconnected from the parent for historical reasons. Several other "gotcha's" apply as well, but when properly set up, it's like magic.


Customer surveys are for companies who didn't pay proper attention to begin with.
Luca Tampellini
Greenhorn

Joined: Apr 28, 2014
Posts: 3
First of all, thank you for the time you spent answering.

Tim Holloway wrote:Welcome to the JavaRanch, Luca!

Aren't you missing something from that stacktrace? When I get a Hibernate JPA rollback exception, it's chained to the exception that initiated the rollback.


As i said this is the sad things about those Rollback: they usually don't have the cause with them since "Transaction marked as rollback only" happens when an Exception or Error is thrown before and gets swallowed by the application.

Tim Holloway wrote:
I'm sure I've missed some details. It's hard to follow stuff that's too big to be seen all at once on the same screen, but I understand that you are committing the parent and child in separate operations. You would be better off doing them both in a single transaction.

In the case of a one-to-many transaction, if you have the correct options set on your entity definitions, committing the parent will automatically commit the child objects. You do need to have the parent and child relationships properly set in your object model when you do this, though. Also, when updating parent-child sets where children may be removed as well as added, JPA2 added an "orphanRemoval" option to get around the case where the in-memory database model gets out of sync with the actual database because removed objects are not by default disconnected from the parent for historical reasons. Several other "gotcha's" apply as well, but when properly set up, it's like magic.


It's a many-to-one on ExternalRoomManagementPermissions that has a single Room as child, and a one-to-many in the User that has a collection ExternalRoomManagementPermissions children.
As i have explained the presence of the first relationship (external management to room) in the code makes the User unable to be updated with the collection of ExternalRoomManagementPermissions (second relationship explained before)
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16145
    
  21

OK. It's my week to be stupid, but I'm not comprehending what the fault in the ORM relationships is. One-to-Many/Many-to-One, most of that is just which direction you're coming from unless there are one-way references involved.

Regardless, the FULL stack trace should contain the actual Hibernate exception AND its JPA-normalized exception. I've dealt with this kind of problem enough to know. If the application code is eating those exceptions, then the application code should be modified.

You may want to switch on some Hibernate tracing options in the log, however. That will allow you to see what's going wrong in more detail, up to and including the actual SQL and data values. Here's some options as defined for the XML config of log4j:



To actually see the ugly details, change the appropriate sub-component's log level to "DEBUG" or "TRACE".
Luca Tampellini
Greenhorn

Joined: Apr 28, 2014
Posts: 3


OK!


I think i've found the problem through intensive debug and extensive use of breakpoints... i've never went so much down in debugging in my whole life as a programmer! The causing error was incredibly stupid:



Somehow the exception was launched inside the Hibernate layer and swallowed in the same place, that's why the RollbackException did not bear any cause in itself. I will probably post a bug signalation on Hibernate forum/groups.

By adding that default empty constructor to the ExternalRoomManagementPermissions i've managed to make the code work!

Big thanks to Tim Holloway from coderanch, Mabi and James Massey from stackoverflow for the help!
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16145
    
  21

Yep. JPA entities must ALWAYS have a default constructor. And for proper operation, should implement hashCode() and equals() methods sufficient to make a given primary key hash well and compare equal between several different objects having the same primary key.

I've traced into Hibernate's code more than once, which is how I found out what a nightmare that fixed-length space-padded keys can be and I commend you on your fortitude. But I'm still fairly sure that that particular message should have shown in the stack trace if the entire exception tree had been displayed.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: RollbackException thrown when adding ManyToOne relationship