Main Tutorials

Cascade – JPA & Hibernate annotation common mistake

Often times, developers are mix used the JPA and Hibernate annotation together, it will caused a very common mistake – JPA cascade type annotation is not working in Hibernate?

During the code review section, i find out many Java developers are not aware of this mistake and causing the program failed to execute the cascade operation to the related entities. I will take this one-to-many hibernate example for the demonstration.

Mistake

In the one-to-many example, many developers declared the JPA cascade options as following :


...
@Entity
@Table(name = "stock", catalog = "mkyong", uniqueConstraints = {
		@UniqueConstraint(columnNames = "STOCK_NAME"),
		@UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
    ...
    private Set<StockDailyRecord> stockDailyRecords = 
                                              new HashSet<StockDailyRecord>(0);
 
    @OneToMany(fetch = FetchType.LAZY, 
       cascade = {CascadeType.PERSIST,CascadeType.MERGE }, 
       mappedBy = "stock")
    public Set<StockDailyRecord> getStockDailyRecords() {
	return this.stockDailyRecords;
    }
 
    public void setStockDailyRecords(Set<StockDailyRecord> stockDailyRecords) {
	this.stockDailyRecords = stockDailyRecords;
    }
    ...

Save it with Hibernate session.


        stockDailyRecords.setStock(stock);        
        stock.getStockDailyRecords().add(stockDailyRecords);
 
        session.save(stock);
        session.getTransaction().commit();

What the code trying to do is when you save a “stock”, it will save the associated stockDailyRecords as well. Everything look fine, but THIS IS NOT WORKING, the cascade options will not execute and save the stockDailyRecords. Can you spot the mistake?

Explanation

Look in the code, @OneToMany is from JPA , it expected a JPA cascade – javax.persistence.CascadeType. However when you save it with Hibernate session, org.hibernate.engine.Cascade will do the following checking …


	if ( style.doCascade( action ) ) {
		cascadeProperty(
	          persister.getPropertyValue( parent, i, entityMode ),
		  types[i],
    	          style,
	          anything,
	          false
		);
	}

The Hibernate save process will causing a ACTION_SAVE_UPDATE action, but the JPA will pass a ACTION_PERSIST and ACTION_MERGE, it will not match and causing the cascade failed to execute.

@see source code

  • org.hibernate.engine.Cascade
  • org.hibernate.engine.CascadeStyle
  • org.hibernate.engine.CascadingAction

Solution

Delete the JPA cascade – javax.persistence.CascadeType, replace it with Hibernate cascade – org.hibernate.annotations.Cascade, with CascadeType.SAVE_UPDATE.


...
@Entity
@Table(name = "stock", catalog = "mkyong", uniqueConstraints = {
		@UniqueConstraint(columnNames = "STOCK_NAME"),
		@UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
    ...
    private Set<StockDailyRecord> stockDailyRecords = 
                                              new HashSet<StockDailyRecord>(0);
 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "stock")
    @Cascade({CascadeType.SAVE_UPDATE})
    public Set<StockDailyRecord> getStockDailyRecords() {
	return this.stockDailyRecords;
    }
 
    public void setStockDailyRecords(Set<StockDailyRecord> stockDailyRecords) {
	this.stockDailyRecords = stockDailyRecords;
    }
    ...

Now, it work as what you expected.

Conclusion

It look like an incompatible issue between JPA and Hibernate cascade annotation, if Hibernate is a JPA implementation, what may causing the misunderstand in between?

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
40 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
vijay
10 years ago

Hi All,

I am new to hibernate , fist Thanks for this post.
I am doing the debug this code and i have requirement i would like to introduce the
delete functionality with annotation i.e once we delete the parent its need to be delete child records ie i need to introduce the ondelete cascade feature.

Could you please help how to introduce this feature.

Thanks
Vijay

Sam Sharaf
9 years ago

This issue unravels only if you use:

Session session = entityManager.unwrap(Session.class);

then use the Hibernate API via the unwrapped session which expects Hibernate annotations not JPA ones. Thus it expects:
@Cascade({CascadeType.SAVE_UPDATE})
But finds:
@OneToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE })

Maksim Gumerov
5 years ago

But isn’t the author telling us that basically Hibernate is not actually JPA-compliant because it does not support JPA cascading defitinions?

Kamal Hussain
7 years ago

HI,

In case of Hibernate onetomany bi-directional relationship with XML configuration when you save child it save parent object and all childs. but if you do same thing with Annotations it is not working. could you please help me in this?

Pooja Garg
7 years ago

Hi,

I tried using org.hibernate.annotations.Cascade : @Cascade({CascadeType.SAVE_UPDATE}) annotation as well. It is not working for me. Can it be jar issue?

SABBAR Kamal
7 years ago

Hi!

Very interesting post, it answers all my questions about that problem.

Thanks.

kamal thapa magar
7 years ago

Hi i am new in spring mvc hibernate can you show small example how to delete parent data from database in one to many realtion

DESH RAJ
8 years ago

Hi,

I have a doubt, In case we have StockDailyRecord that is common between two Stocks(Just suppose), And we don’t want duplicate records in StockDailyRecord table then how we will handle it.?

I have posted same problem at below link please a look and suggest the solution.
http://stackoverflow.com/questions/31241507/how-to-prevent-cascadecascadetype-all-to-saving-duplicate-duplicate-records

Petr
9 years ago

Hi,
you just saved me lot of time. Article is still valid.

Idea 14 generated entites +Hibernate JPA 2.0

Steven Hunter
10 years ago

At the very least, you should point out that switching from the JPA notation to the hiberate trades off portability of your code to other JPA venders

Anup Mehta
10 years ago

This article is extremely confusing .
I saw one of your example where you used JPA cascade option
https://mkyong.com/hibernate/hibernate-one-to-one-relationship-example-annotation/
(refer stock.java )
And than later you used hibernate’s sesssion.save(stock)
On net too I have observed that people use CascadeType.All and use session.save(object) and the code works fine .
Does this mean that save() method exists in both Hibernate and JPA ? Please clear my doubt.

usebrain
9 years ago
Reply to  Anup Mehta

valid question..did you get the answer…if so do share to all please

Dawid Furman
10 years ago

Yeah! Thank you very much for your great article!! Now all is clear!
best regard from Poland

dan carter
10 years ago

Hi,

As this article is quite highly ranked in google still, it’s worth pointing out that hibernate does now support JPA cascade. No need to use the hibernate specific annotation.

import javax.persistence.CascadeType;
import javax.persistence.FetchType;
import javax.persistence.OneToOne;

@OneToOne(mappedBy = “device”, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private LoginService loginService;

Using 4.2.3-Final here

Pooja Garg
7 years ago
Reply to  dan carter

4.2.3 final version of which jar? Hibernate-annotations or hibernate-core jar. I tried using JPA jars as well. Cascade delete is not working for me. I am having both OneToMany and ManyToOne annotation. Is it required to have cascade with both the annotation?

dan carter
10 years ago
Reply to  dan carter

Actually, i should point out i am using JPA API here to save (well actually using spring-data which in turn uses jpa entity-manager)

And actually re-reading this article i see i have misunderstood it. Ii thought you were talking about how to use hibernate with JPA, but in fact you are explaining how to use the hibernate native API with no JPA at all.

Muhammad Bilal
10 years ago

I have been working on this issue for a long time .. didnt got this clicked in ma mind. your blog help Alot. Thanks

Laxmikanth
10 years ago

Even I was struggling why Hibernate is not saving child objects. Your blog helped me dude..
Thanks alot..!!

Abhay
10 years ago

Any recommended book for JPA & JPQL.
thanks in advance…

srinu
10 years ago

its good..

Shivang Gupta
10 years ago

Thanks a lot!! I was facing this exact issue. Saved me some time in identifying the problem, and a lot of time in finding the solution. This post, as well as others (especially those on Spring) have been a big help. Keep blogging and enlightening us… 🙂

nelson
10 years ago

It would be greate if there was a searchBox in the site.

Arup
11 years ago

helps a lot.

dli7mar
11 years ago

Hi mkyong,

In a JPA/Hibernate project, can I define a generic method in dao class like this:

public void save(T entity) {
em.persist(entity);
}

and then call this method in managed beans, pass in different entities?
I would like to avoid having multiple save methods in dao, one for each entity class.

Many Thanks.

usebrain
9 years ago
Reply to  dli7mar

did you get a reply…if so do help others like me 😉
Thanks

chades
9 years ago
Reply to  usebrain

Hi there, Yes you can use generic implementation to cut off lots of boilerplate codes on your persistence layer implementations. Let me know if you need any help around this.

Sina
11 years ago

I have a ManyToMany relation (Role – Activity – RoleActivity).
In Role Entity I have added @Cascade({CascadeType.DELETE_ORPHAN })
But while deleting a role I have this error:
java.sql.SQLIntegrityConstraintViolationException: ORA-02292: integrity constraint (USR_SPS.FG_RL_ID) violated – child record found
It seems hibernate annotation doesnt work fine

Alex
12 years ago

I am using JPA2 and hibernate 3.6. Until now I was able to implement everything I wanted using only JPA-annotations.
I exclusively use JPA-Annotations and EntityManager. And there’s absolutely nothing wrong (except for and probably atomikos related issue, which is likely to be a configuration fault).

I think the main mistake is mixing up hibernate and JPA. At design time you should make a decision which one you are going to use and then you have to stick to it. If you don’t you’re using bad design.

In my opinion it would be less confusion for beginners, if you point this out. This topic suggests Hibernate has a generel problem with CascadeType or maybe other JPA-annotations.

marcher
13 years ago

I cannot thank you enough! You saved me from spending many more hours digging around and “experimenting” to solve foreign key constraint issues. :’) I have a comment though: for the Hibernate CascadeType to “kick in” I still needed to specify the JPA one in my entity. Per Hibernate’s documentation on cascading ( http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#entity-hibspec-cascade ) this is recommended, but in my case it seems to be actually required 😐

Anyway, thanks a lot, again 🙂

10 years ago
Reply to  marcher

You both are godsends. Adding the “optional” JPA annotation from the docs fixed my cascade. I wasted time “experimenting” with the foreign keys and annotations for my objects and tables.

Dhiraj
13 years ago
Reply to  marcher

Thanks for this post. I had to debug all the way down to figure this insconsistency.

vijay
10 years ago
Reply to  mkyong

Hi Yong,

I am new to hibernate , fist Thanks for this post.
I am doing the debug this code and i have requirement i would like to introduce the
delete functionality with annotation i.e once we delete the parent its need to be delete child records ie i need to introduce the ondelete cascade feature.

Could you please help how to introduce this feature.

vijay
10 years ago
Reply to  mkyong

Hi Yong,

I am new to hibernate , fist Thanks for this post.
I am doing the debug this code and i have requirement i would like to introduce the
delete functionality with annotation ie once we delete the parent its need to be delete child records ie i need to introduce the ondelete cascade feature.
Could you please help how to introduce this feature.

Neal
13 years ago

Yep ran into this issue headfirst…and helped me solve. Thanks a bunch.
But now my code is tied to Hibernate – which goes against JPA principles:)
So is there a newer version of JPA that fixes this issue?
I couldn’t find this problem mentioned anywhere else.
Does Oracle/Sun know about this issue to fix in their next version?
would you know?

Edmund Leng
13 years ago

I thought you should be using EntityManager which is created to solve problems of such nature.

Maarten
14 years ago

CascadeType.PERSIST will work when using session.persist() instead of session.save()

roshi
11 years ago
Reply to  Maarten

Thanks for that tip saved the mixing up of hibernate annotations with jpa