Search code examples
javahibernatejpahibernate-mapping

Hibernate don't cascade update on specific field


I have a mapping problem with hibernate. In a @OneToOne relationship, I don't want to cascade the update to the partner. This is my current mapping:

Entity class:

public class Entity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @OneToOne(orphanRemoval = false)
    @JoinColumns({
        @JoinColumn(name = "instrumentMandant", referencedColumnName = "mandant", updatable = false, insertable = false, nullable = true),
        @JoinColumn(name = "instrumentId", referencedColumnName = "internalId", updatable = false, insertable = false, nullable = true) })
    private Instrument instrument;
}

and Instrument:

public class Instrument{
    @Id
    private Integer internalId;
    @Id
    private Integer mandant;

    @OneToOne(mappedBy = "instrument")
    private Entity entity;
}

Whenever I update my Entity class, the Instrument should not be updated. As you can see, I tried with updateable = false, but it still trys to update. I know that because of this error:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Instrument

My only workaround to far is to call setInstrument(null); prior to the update call. Yet I believe that this should be possible with mapping configuration, but couldn't find a way to do it.

So my question is, how can I tell hibernate not to update Instrument when updating Entity (configured by mapping)?


Update as requested:

sessionFactory.getCurrentsession().merge(entity);

There are no other changes whatsoever inside the transaction


Solution

  • The problem is that you have a persistent object (Entity) - that object is successfully merged. Then that persistent object has a relationship to another object that is also managed. i.e. the code is telling hibernate that it must manage that object as well (Instrument).

    Because you have told hibernate not to cascade the merge hibernate does not also merge the instrument object. Thus when hibernate tries to complete the transaction you get the error because at the end of the merge there is the Entity object which is persisted with a link to the Instrument which should be persisted but is not.

    You work around is not in fact a work around at all but the exact way to achieve what it sounds like you're after.

    Or do you want the current persisted instrument object to be the one that is linked with Enity? In that case you will have to load it and set it yourself.

    A more interesting question is why you don't want the instrument object persisted as it is marked for persistence.