orphan removal constraint violation - jpa-2.0

I am using EclipseLink and have the following entity classes (I tried to simplify the scenario as much as I could, but after any further simplification, the error does not occur):
#Entity
public class A {
#Id
#GeneratedValue
private long id;
#OneToOne(cascade = CascadeType.ALL, orphanRemoval=true)
private AbstractB b;
}
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class AbstractB {
#Id
#GeneratedValue
protected long id;
}
#Entity
public class BImpl extends AbstractB {
#OneToOne(cascade = CascadeType.ALL, orphanRemoval=true)
private D d;
}
#Entity
public class D {
#Id
#GeneratedValue
private long id;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#Size(min = 1)
private Set<C> cs = new HashSet<C>();
}
#Entity
public class C {
#Id
#GeneratedValue
private long id;
}
with an instance of A referencing a BImpl, which references a D, which in turn holds an instance of C in a set.
As you can see in the code, all references have orphanremoval set to true and CascadeType.ALL.
When I set the reference of A->AbstractB to null and merge back the instance of A, the following constraint violation occurs:
20:05:03,388 INFO [STDOUT] [EL Fine]: 2012-04-13 20:05:03.388--ClientSession(2132156535)--Connection(1281180651)--Thread(Thread[http-0.0.0.0-443-2,5,jboss])--UPDATE A SET B_ID = ? WHERE (ID = ?)
20:05:03,388 INFO [STDOUT] bind => [null, 1]
20:05:03,390 INFO [STDOUT] [EL Fine]: 2012-04-13 20:05:03.39--ClientSession(2132156535)--Connection(1281180651)--Thread(Thread[http-0.0.0.0-443-2,5,jboss])--DELETE FROM BIMPL WHERE (ID = ?)
20:05:03,390 INFO [STDOUT] bind => [2]
20:05:03,391 INFO [STDOUT] [EL Fine]: 2012-04-13 20:05:03.391--ClientSession(2132156535)--Connection(1281180651)--Thread(Thread[http-0.0.0.0-443-2,5,jboss])--DELETE FROM ABSTRACTB WHERE (ID = ?)
20:05:03,391 INFO [STDOUT] bind => [2]
20:05:03,392 INFO [STDOUT] [EL Fine]: 2012-04-13 20:05:03.392--ClientSession(2132156535)--Connection(1281180651)--Thread(Thread[http-0.0.0.0-443-2,5,jboss])--DELETE FROM C WHERE (ID = ?)
20:05:03,393 INFO [STDOUT] bind => [4]
20:05:03,393 INFO [STDOUT] [EL Fine]: 2012-04-13 20:05:03.393--ClientSession(2132156535)--Thread(Thread[http-0.0.0.0-443-2,5,jboss])--SELECT 1
20:05:03,394 INFO [STDOUT] [EL Warning]: 2012-04-13 20:05:03.394--UnitOfWork(2142376869)--Thread(Thread[http-0.0.0.0-443-2,5,jboss])--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
20:05:03,394 INFO [STDOUT] Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`db`.`D_C`, CONSTRAINT `FK_D_C_cs_ID` FOREIGN KEY (`cs_ID`) REFERENCES `C` (`ID`))
20:05:03,394 INFO [STDOUT] Error Code: 1451
20:05:03,395 INFO [STDOUT] Call: DELETE FROM C WHERE (ID = ?)
20:05:03,395 INFO [STDOUT] bind => [4]
Could anyone explain to me, why the D_C entry does not get deleted before the C instance?

adding #CascadeOnDelete may solve your problem
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#CascadeOnDelete
#Size(min = 1)
public Set<TestChild> childrenSet = new HashSet<TestChild>();
see also: EclipseLink DeleteCascade
HTH Danny

Related

Hibernate criteria cannot fetch rows could not resolve property

Hi i have these 2 basic entity mapping for postgresql db, and i have wrote criteria for
fetching all activated user which have same key it is showing this error
org.hibernate.QueryException: could not resolve property: key.id of: com.sar.dfsapp.modal.ActivatedUser
#Entity
#Table(name = "activated_user")
public class ActivatedUser implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false, length = 11)
private long id;
#ManyToOne
#JoinColumn(name = "key_id", nullable = false)
private Key key;
}
#Entity
#Table(name = "key")
public class Key implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false, length = 11)
private long id;
#Column(name = "key_code", nullable = false)
private String keyCode;
}
Below is my criteria i have tried.
Criteria c = getSession().createCriteria(ActivatedUser.class);
c.add(Restrictions.eq("key.id", id));
List<ActivatedUser> result = c.list();
try this :
Criteria c = getSession().createCriteria(ActivatedUser.class);
Criteria keyCriteria = criteria.createCriteria("key", CriteriaSpecification.INNER_JOIN);
keyCriteria.add(Restrictions.eq("id", id));
List<ActivatedUser> result = c.list();
it there the same error ?

TransactionRolledbackLocalException

I'm having an annoying error message while trying to insert new element in a one to many relationship using JPA 2.0.
public class Ordinateur implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "TAG")
private BigInteger tag;
#Size(max = 30)
#Column(name = "MACHINE")
private String machine;
#Size(max = 25)
#Column(name = "NOM_FABRIQUANT")
private String nomFabriquant;
#Column(name = "NUM_SERIE")
private BigInteger numSerie;
#Column(name = "ADRESSE_IP")
private BigInteger adresseIp;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "NUM_SEQ")
private BigInteger numSeq;
#Size(max = 30)
#Column(name = "SYSTEME_EXPLOITATION")
private String systemeExploitation;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 30)
#Column(name = "IDORD")
private String idord;
#OneToMany(mappedBy = "idord")
private List<Systemeexploitation> systemeexploitationList;
#OneToMany(mappedBy = "idord")
private List<Intervention> interventionList;
#OneToMany(mappedBy = "idord")
private List<Inventaire> inventaireList;
public Ordinateur() {
} //...........
my session bean :
public void ordCreer(Ordinateur ordinateur) {
ordinateurFacade.create(ordinateur);
}
Managed Bean :
public String enregistrerOrd() throws Exception{
manager.ordCreer(ordinateur);
return "OrdList";
}
and here's the error :
ATTENTION: EJB5184:A system exception occurred during an invocation on EJB OrdinateurFacade, method: public void ejb.AbstractFacade.create(java.lang.Object)
ATTENTION: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
at com.sun.ejb.containers.BaseContainer.checkExceptionClientTx(BaseContainer.java:5071)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4906)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:89)
at $Proxy312.create(Unknown Source)
at ejb.__EJB31_Generated__OrdinateurFacade__Intf____Bean__.create(Unknown Source)
//...
Caused by: javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.
//...
TTENTION: EJB5184:A system exception occurred during an invocation on EJB Manager, method: public void DAO.Manager.ordCreer(jpa.Ordinateur)
ATTENTION: javax.ejb.EJBTransactionRolledbackException
at com.sun.ejb.containers.BaseContainer.mapLocal3xException(BaseContainer.java:2314)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2096)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:89)
at $Proxy312.create(Unknown Source)
at ejb.__EJB31_Generated__OrdinateurFacade__Intf____Bean__.create(Unknown Source)
//................
Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
at com.sun.ejb.containers.BaseContainer.checkExceptionClientTx(BaseContainer.java:5071)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4906)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045)
... 80 more
Caused by: javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.
at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.validateOnCallbackEvent(BeanValidationListener.java:90)
at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.prePersist(BeanValidationListener.java:62)
at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyListener(DescriptorEventManager.java:698)
I tryed to delete the #NotNull but nothing happened
Any idea of the reason?

JPA StackOverflowError when loading data in relationship tables

I'm trying to implement loading in three tables (the beginning of the problem with mapping)
Products:
#Entity
#Table(name = "products")
public class Product implements Serializable {
#Id
#Column(name = "id")
private Integer id;
#OneToMany(mappedBy = "property", fetch = FetchType.LAZY)
private Collection<ProductProperty> productPropertyCollection;
...
}
Properties:
#Entity
#Table(name = "properties")
public class Property implements Serializable {
#Id
#Column(name = "id")
private Integer id;
#OneToMany(mappedBy = "property", fetch = FetchType.LAZY)
private Collection<ProductProperty> productPropertyCollection;
...
}
Product_Property
#Entity
#Table(name = "product_property")
public class ProductProperty implements Serializable {
#EmbeddedId
protected ProductPropertyPK productPropertyPK;
#MapsId(value = "propertyId")
#JoinColumn(name = "property_id", referencedColumnName = "id")
#ManyToOne()
private Property property;
#MapsId(value = "productId")
#JoinColumn(name = "product_id", referencedColumnName = "id")
#ManyToOne()
private Product product;
...
}
#Embeddable
public class ProductPropertyPK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "product_id", insertable = false, updatable = false)
private int productId;
#Basic(optional = false)
#NotNull
#Column(name = "property_id", insertable = false, updatable = false)
private int propertyId;
...
}
It works fine for 1, 10, 100 products, but somewhere there is an error, because for 1000 and more products throws error:
Caused by: java.lang.StackOverflowError
at java.util.HashMap.getEntry(HashMap.java:443)
at java.util.HashMap.containsKey(HashMap.java:434)
at java.util.HashSet.contains(HashSet.java:201)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.discoverAndPersistUnregisteredNewObjects(UnitOfWorkImpl.java:4141)
at org.eclipse.persistence.mappings.ObjectReferenceMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectReferenceMapping.java:938)
at org.eclipse.persistence.mappings.ObjectReferenceMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectReferenceMapping.java:916)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectBuilder.java:1964)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.discoverAndPersistUnregisteredNewObjects(UnitOfWorkImpl.java:4178)
at org.eclipse.persistence.mappings.CollectionMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(CollectionMapping.java:426)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectBuilder.java:1964)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.discoverAndPersistUnregisteredNewObjects(UnitOfWorkImpl.java:4178)
at org.eclipse.persistence.mappings.ObjectReferenceMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectReferenceMapping.java:938)
at org.eclipse.persistence.mappings.ObjectReferenceMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectReferenceMapping.java:916)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectBuilder.java:1964)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.discoverAndPersistUnregisteredNewObjects(UnitOfWorkImpl.java:4178)
at org.eclipse.persistence.mappings.CollectionMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(CollectionMapping.java:426)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectBuilder.java:1964)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.discoverAndPersistUnregisteredNewObjects(UnitOfWorkImpl.java:4178)
at org.eclipse.persistence.mappings.ObjectReferenceMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectReferenceMapping.java:938)
at org.eclipse.persistence.mappings.ObjectReferenceMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectReferenceMapping.java:916)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectBuilder.java:1964)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.discoverAndPersistUnregisteredNewObjects(UnitOfWorkImpl.java:4178)
...
when i'm creating ProductProperty, i'm setting product and property in ProductProperty, and adding to collection for bidirection in Product and Property.
where i could make a mistake?
Looks like your object model complexity or depth is just difficult to traverse within your JVM's stack limits. As it is, every entity seems reachable from every other entity, which causes problems when traversed recursively. Try increasing the -Xss setting. You might also reduce the interconnectivity, such as removing one of the OneToMany mappings and query for it directly instead of storing it in the Product or Property mapping. You might also file an enhancement with EclipseLink to traverse the object graph using a stack instead of recursively.

JPA, compound key with foreign keys + persist oneToMany

I'm trying to do something with JPA that'll use a lot on a project but I'm stuck.
I have 2 entities + a kind of "glue" entity, I'll call them
ClassA
ClassB
Glue
I want to add a new ClassA with new Glues set in it's list, ClassB's already exist.
That would do something like :
ClassA 1 | Glue 1 1 | ClassB 1
ClassA 1 | Glue 1 2 | ClassB 2
ClassA 1 | Glue 1 3 | ClassB 3
ClassA 1 | Glue 1 4 | ClassB 4
So as said ClassA and all Glues are to be inserted, ClassA has a List with the new Glues to be inserted.
Here they are :
#Entity
public class ClassA implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
(...)
#OneToMany(cascade = CascadeType.ALL, mappedBy = "classA")
private List<Glue> glueList;
(...)
}
#Entity
public class ClassB implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
(...)
}
#Entity
public class Glue implements Serializable {
#EmbeddedId
protected GluePK gluePK;
#JoinColumn(name = "id_class_a", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private ClassA classA;
#JoinColumn(name = "id_class_b", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private ClassB classB;
(...)
}
#Embeddable
public class GluePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "id_class_a", nullable = false)
private int idClassA;
#Basic(optional = false)
#NotNull
#Column(name = "id_class_b", nullable = false)
private int idClassB;
(...)
}
When I try to persist my ClassA I'm getting something like :
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
Cannot add or update a child row: a foreign key constraint fails (bdd.glue, CONSTRAINT constraint_name FOREIGN KEY (id_class_a) REFERENCES ClassA (id) ON DELETE NO ACTION ON UPDATE NO ACTION)
I understand that he complains that Glues dont have ClassA's reference set but I'd like him to fill it just then he persists ClassA.
Is this achievable?
If not what's the best way to do it?
I'd like to stay on JPA without any specific vendor tricks (I'm using eclipselink) but if some vendor can do it easily I'll go for it.
Thanks!
I would remove the EmbeddedId, use an IdClass instead and just add the #Id to the #ManyToOne mappings.
See,
http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#JPA_2.0
Or maybe even give Glue an id of its own.
You could also remove the insertable = false, updatable = false from the #ManyToOne and move them to the EmbeddedId.

Not Null Property Exception with JPA onetoone mapping

I am trying my way around JPA but I cant get this to work the way I understand them.
Its the onetoone bidirectional mapping between an Order and an OrderInvoice class which is a required
association
My entities are marked as this
#Entity
#Table(name = "Orders")
public class Order {
#Id
#GeneratedValue
#Column(name = "ORDER_ID")
private int orderId;
#OneToOne(optional=false,cascade=CascadeType.ALL, mappedBy="order", targetEntity=OrderInvoice.class)
private OrderInvoice invoice;
}
#Entity
#Table(name = "ORDER_INVOICE")
public class OrderInvoice {
#Id
#GeneratedValue
#Column(name = "INVOICE_ID", nullable = false)
private int invoiceId;
#OneToOne(optional = false)
#JoinColumn(name="ORDER_ID")
private Order order;
}
My test class is like this.
#Test
public void createOrder() {
Order order = createOrderImpl();
assertNotNull(order);
}
private Order createOrderImpl() {
OrderInvoice orderInvoice = new OrderInvoice(new Date(), 100.0, null,
null, new Date());
Order order = new Order(100.0, "JOHN Doe's Order", new Date(), new Date(),orderInvoice);
orderDao.create(order);
return order;
}
But I am encountering below problem when I run my Test
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: order.OrderInvoice.order
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: order.OrderInvoice.order
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:95)
try to
orderInvoice.setOrder(order);
orderDao.create(order);