Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate cascade update gives null pointer

Tags:

java

hibernate

I have the following entity which works fine during hibernate insert.

User.java

@Entity
@Table
@Inheritance(strategy = InheritanceType.JOINED)
public class User extends PersistentObject {

    private static final long serialVersionUID = -1803375723276957167L;

    // commenting this association allows update to work successfully.
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private ContactInfo contactInfo;
    private String name;
}

Then, I tried to perform update on an entity that I believe it is detached and get null pointer exception during cascadeOnUpdate.

Exception

java.lang.NullPointerException
    at org.hibernate.engine.spi.EntityEntry.getLoadedValue(EntityEntry.java:274)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:236)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:132)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:361)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:335)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:239)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:109)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:724)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:716)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:712)
    at com.myapp.dao.GenericHibernateDAO.save(GenericHibernateDAO.java:279)
    at com.myapp.service.StaffInfoServiceImpl.storeInfo(StaffInfoServiceImpl.java:74)
    at com.myapp.service.StaffInfoServiceImpl.storeInfo(StaffInfoServiceImpl.java:1)

UPDATE

ContactInfo.java

@Entity
@Table
@DynamicUpdate
public class ContactInfo implements Serializable {

    private static final long serialVersionUID = 4485388013971134422L;

    @Column
    @Length(min = 3, max = 50)
    private String currentCity;

    @ManyToOne
    @JoinColumn(name = "current_country_id")
    private Country currentCountry;

    @Column(columnDefinition = "char(10)")
    private String currentPostCode;

    @Column
    @Length(min = 3, max = 50)
    private String currentState;

    @Column
    @Length(min = 3, max = 50)
    private String currentStreetOne;

    @Column
    @Length(min = 3, max = 50)
    private String currentStreetThree;

    @Column
    @Length(min = 3, max = 50)
    private String currentStreetTwo;

    @Column
    @Email
    private String email;

    @Column
    @Length(max = 20)
    private String fax;

    @Column
    @Length(max = 20)
    private String homePhone;

    @GenericGenerator(name = "generator", strategy = "foreign", parameters = @Parameter(name = "property", value = "user"))
    @Id
    @GeneratedValue(generator = "generator")
    @Column(name = "user_id", unique = true, nullable = false)
    private Long id;

    @Column
    @Length(max = 20)
    private String mobilePhone;

    @Column
    @Length(max = 20)
    private String officePhone;

    @Column
    @Length(min = 3, max = 50)
    private String permanentCity;

    @ManyToOne
    @JoinColumn(name = "permanent_country_id")
    private Country permanentCountry;

    @Column(columnDefinition = "char(10)")
    private String permanentPostCode;

    @Column
    @Length(min = 3, max = 50)
    private String permanentState;

    @Column
    @Length(min = 3, max = 50)
    private String permanentStreetOne;

    @Column
    @Length(min = 3, max = 50)
    private String permanentStreetThree;

    @Column
    @Length(min = 3, max = 50)
    private String permanentStreetTwo;

    @OneToOne(fetch = FetchType.LAZY)
    @PrimaryKeyJoinColumn
    private User user;

    @Version
    @Column(name = "version")
    private Integer version = 0;   
}

My question is why during insert the exception is not thrown while during update it is ? What did I miss here ?

like image 213
abiieez Avatar asked Apr 09 '26 18:04

abiieez


2 Answers

This is bug of hibernate, that was fixed in version 4.1.7.
Temporary workaround for your version, use session.merge instead of session.saveOrUpdate.

Problem was fixed under this task

like image 54
Ilya Avatar answered Apr 11 '26 06:04

Ilya


I think this error is because of the orphanRemoval = true property in the @OneToOne association.

When you update the User with null reference to ContactInfo, the hibernate might be assuming that the ContactInfo reference was set to null and then it try to remove the object that 'was there(but never existed)' because of the orphanRemoval semantic.

If my logic about this error is true, there is one bug in the hibernate. Maybe this is fixed in a newer version of hibernate.

like image 45
fmodos Avatar answered Apr 11 '26 07:04

fmodos