Am struggling for almost a day trying to prevent saving to child entity(USER) it will have value already so dont perform insert/update on user from company.
Reference Links
How to avoid insert and update queries in one-to-many uni-directional association
How to prevent saving child object with JPA?
JPA: Prevent cascade parent from saving
Actual code:
Company:
#OneToMany(mappedBy = "parentCompany")
private List<User> users;
User:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID_COMPANIES")
private Company parentCompany;
Tried one by one
#OneToMany(mappedBy = "parentCompany", cascade = CascadeType.PERSIST)
#JoinColumn(name = "ID_USERS", insertable = false, updatable = false)
private List<User> users;
#OneToMany(mappedBy = "parentCompany")
#JoinColumn(name = "ID_USERS", insertable = false, updatable = false)
private List<User> users;
#OneToMany(mappedBy = "parentCompany", fetch = FetchType.LAZY)
private List<User> users;
// called getuser().size to initialize
#OneToMany(mappedBy = "parentCompany", fetch = FetchType.EAGER)
private List<User> users;
// called getuser().size to initialize and its returning vector but insert not preventing.
Saving:
public T update(T t) {
return this.entityManager.merge(t);
}
Error:
Caused by:
java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.volvocars.tis.domain.model.User#4.
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:313)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:727)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:441)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:878)
at org.eclipse.persistence.internal.jpa.QueryImpl.performPreQueryFlush(QueryImpl.java:967)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeUpdate(QueryImpl.java:296)
at com.volvocars.tis.domain.dao.bean.CompanyAddressDaoBean.updateVolvoAddress(CompanyAddressDaoBean.java:99)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.EJSContainer.invokeProceed(EJSContainer.java:4886)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:592)
at com.ibm.ws.cdi.ejb.impl.InterceptorChain.proceed(InterceptorChain.java:119)
at com.ibm.ws.cdi.ejb.impl.EJBCDIInterceptorWrapper.invokeInterceptors(EJBCDIInterceptorWrapper.java:131)
at com.ibm.ws.cdi.ejb.impl.EJBCDIInterceptorWrapper.aroundInvoke(EJBCDIInterceptorWrapper.java:54)
at sun.reflect.GeneratedMethodAccessor59.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.interceptors.InterceptorProxy.invokeInterceptor(InterceptorProxy.java:189)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:577)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64)
at com.ibm.ws.cdi.ejb.interceptor.WeldSessionBeanInterceptorWrapper.aroundInvoke(WeldSessionBeanInterceptorWrapper.java:58)
at sun.reflect.GeneratedMethodAccessor58.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.interceptors.InterceptorProxy.invokeInterceptor(InterceptorProxy.java:189)
How to prevent saving child entity on particular case? Any way can achieve programmatically or with annoation?
Related
I am trying to do a "many to many" jpa mapping.
I have a table called "Account":
#ManyToMany(fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
#JoinTable(name = "account_user",
joinColumns = { #JoinColumn(name = "account_id") },
inverseJoinColumns = { #JoinColumn(name = "user_id") })
private Set<User> users = new HashSet<>();
I have table called "User":
#ManyToMany(fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
},
mappedBy = "user")
#JsonIgnore
private Set<Account> accounts = new HashSet<>();
I get the following error:
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.bank.account.model.Account.user in com.bank.account.model.User.accounts
A join "many to many" table called "AccountUser" is supposed to be created by the mapping.
Any help or hint would be greatly appreciated it!!
MappedBy must refer to the attribute name in the target class. In your case it's users not user.
#ManyToMany(fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
},
mappedBy = "users")
#JsonIgnore
private Set<Account> accounts = new HashSet<>();
Comment class
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_id")
private User user;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "image_id")
private Image image;
User class
#OneToMany(mappedBy = "user", cascade = CascadeType.MERGE, fetch =
FetchType.EAGER)
private List<Comment> comments = new ArrayList<>();
Image class
#OneToMany(mappedBy = "image",cascade = CascadeType.MERGE,fetch =
FetchType.EAGER)
private List<Comment> comments = new ArrayList<Comment>();
These are the ManyToOne and OneToMany relations I have. I am unable to persist the Comment object due to "detached entity passed to persist: ImageHoster.model.Comment" error.
I kind of figured out the issue. In the CommentRepository class where I am persisting the Comment object, I used .merge instead of .persist
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
try{
transaction.begin();
em.merge(newComment);
instead of em.persist(newComment);
My problem is that I'm getting LazyInitializationException.
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:148) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at sk.kristian.dienes.eshop.entity.SubCategory_$$_jvsta89_5.hashCode(SubCategory_$$_jvsta89_5.java) ~[main/:na]
at sk.kristian.dienes.eshop.entity.Product.hashCode(Product.java:18) ~[main/:na]
I have two #ManyToOne relationships in one class
public class Product implements Serializable{
#Id
#Column(name = "id")
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_category")
private Category category;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_sub_category")
private SubCategory subCategory;
}
#Entity
#Data
public class SubCategory implements Serializable {
#OneToMany(mappedBy = "subCategory", cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private List<Product> products;
}
#Entity
#Data
public class Category implements Serializable {
#OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Product> products;}
I'm using HttpSession.
I've also tried to add this property spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true but It did not helped. I would like to know if there is any solution. Also tried to use Transactional anotation in services.
The problem is you try to call object that is detached.
For example)
Product product = em.find(Product.class, id)
// somewhere `em.detach(product)` is called.
product.getCategory(); // It raises Exception
I don't know what you try with those objects. But you should reattach entity to EntityManager like em.merge(detachedObject)
Check state of EntityManager
https://vladmihalcea.com/a-beginners-guide-to-jpahibernate-entity-state-transitions/
I have #OneToMAny realationship inside my entity.
Is it possible to disable jpa from generating select for the joined column? beacuse I have many records in my main table and when selecting them , each record performs select for the joined column. I would like to disable this select is that possible?
UPDATE:
I tried inserting fetch LAZY but it still creates a select for Table02f and Table03f...
This is my code:
public class Table01f implements Serializable {
#OneToMany(fetch=FetchType.LAZY , cascade = CascadeType.ALL, mappedBy = "table01f")
private List<Table02f> table02fList;
//getter & setter...
}
public class Table02f implements Serializable {
#JoinColumn(name = "F2PRP", referencedColumnName = "F1PRP", insertable = false, updatable = false)
#ManyToOne(optional = false)
#JsonIgnore
private Table01f table01f;
#OneToMany(fetch=FetchType.LAZY , cascade = CascadeType.ALL, mappedBy = "table02f")
private List<Table03f> table03fList;
//getter & setter...
}
public class Table03f implements Serializable {
#JoinColumns({
#JoinColumn(name = "F3PRP", referencedColumnName = "F2PRP", insertable = false, updatable = false),
#JoinColumn(name = "F3BRN", referencedColumnName = "F2BRN", insertable = false, updatable = false)})
#ManyToOne(optional = false)
#JsonIgnore
private Table02f table02f;
//getter & setter...
}
Thank's In Advance.
Just add the fetch type LAZY to your #OneToMany relationship:
#OneToMany(fetch=FetchType.LAZY)
When you load the list of your main entities, JPA won't populate your list for this relationship, avoiding the generation of the SELECT.
Just have a look at this functionality in JPA documentation so that you can understand how to use it.
If you don't need the data make it LAZY (in general always make everything LAZY).
If you need the data, then you can use batch fetching, or join fetching.
http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html
I am trying to persist the following entity:
public class CommentEntity {
#Id
#ManyToOne(optional=false,cascade=CascadeType.REFRESH, targetEntity=UserEntity.class)
#JoinColumn(name="USERID",referencedColumnName="USERID")
private UserEntity userEntity;
#ManyToOne(optional=false,cascade=CascadeType.REFRESH, targetEntity=PostEntity.class)
#JoinColumn(name="POSTID",referencedColumnName="POSTID")
private PostEntity postEntity;
}
But the error comes out:
During synchronization a new object was found through a relationship that was not marked cascade PERSIST: entity.PostEntity#16afec.
when I try to persist PostEntity, it is persisted. No such exception is thrown:
public class PostEntity {
#ManyToOne(optional = false, cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, targetEntity = UserEntity.class)
#JoinColumn(name = "USERID", referencedColumnName = "USERID")
private UserEntity userEntity;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "postEntity", fetch = FetchType.LAZY)
private List<CommentEntity> commentEntityList;
}
Why it is happening? UserEntity is:
public class UserEntity {
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "userEntity")
private List<PostEntity> postEntityList;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "userEntity")
private List<CommentEntity> commentEntityList;
}
I am persisting commentEntity using the code:
entityManagerFactory = Persistence
.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
entityManager = entityManagerFactory.createEntityManager();
entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
entityManager.persist(commentEntity);
entityTransaction.commit();
entityManager.close();
I am not able to understand what can be the cause? And then why PostEntity is getting persisted in the same situation?
I am using EclipseLink
Because you try to persist CommentEntity that have either userEntity or postEntity (or both) referencing to the entity that is not persisted. Call to em.persist(instance of commentEntity) does not cause those entities to be persisted, because you cascaded only refresh. You should persist those entities with separate calls to em.persist.
If this does not answer to your question, please provide the code that creates entities and persists them.