How to delete parent without deleting children in one to many relationship - java

I am trying to delete a Patient entity without deleting the associated OutboundMessage entities as i want to keep them in the database for reporting/historical purposes. This is the relevant code :
Patient entity
#OneToMany (mappedBy="patient", fetch = FetchType.EAGER,orphanRemoval = false)
public Set<OutboundMessage> getOutboundMessages()
{
return outboundMessages;
}
OutboundMessage entity
#ManyToOne (fetch=FetchType.EAGER)
#JoinColumn(name = "id_patient")
public Patient getPatient()
{
return patient;
}
When i set a cascade type on the Patient side the records are deleted which is not what i want. When trying as shown in the code above (without the cascade type) I get the following exception :
The DELETE statement conflicted with the REFERENCE constraint "FKqjpga9w6wp3qk26ox9pg252d9". The conflict occurred in database "MDHIS", table "dbo.tblOutboundMessage", column 'id_patient'.
What settings does the owning entity need to allow deletion without cascading to children entities and without cleaning orphaned records?
Thanks!

You need to allow null values in your foreign key column (#JoinColumn) as follows:
#ManyToOne (fetch=FetchType.EAGER)
#JoinColumn(name = "id_patient", nullable = true)
public Patient getPatient() {
return patient;
}
Then in your DAO you need to set null values for all the OutboundMessage related to the Patient you're about to delete and only then delete it, as follows:
public void deletePatient(int patientId) {
Session currentSession = sessionFactory.getCurrentSession();
// get patient with primary key
Patient patient = currentSession.get(Patient.class, patientId);
Set<OutboundMessage> messages = patient.getOutboundMessages();
//set patient id null
for(OutboundMessage message : messages) {
message.setPatient(null);
}
//delete the patient
currentSession.remove(patient);
}

Related

JPA bidirectional relation, JoinColumn not populated [duplicate]

I have one to many relationships between person class and car class. A person can own many cars and vice versa. I am using restful API to post data. My annotations and Get service is working fine but my post service throws " java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL" error whenever I try to insert new data. Child table foreign key is being inserted as null.
Here is part of my code.
Person.java
private List<Car> cars = new ArrayList<Car>();
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="person")
#JsonManagedReference
public List<Car> getCars() {
return cars;
}
Car.java
private Person person;
#ManyToOne
#JoinColumn(name = "PERSON_ID", nullable = false, updatable = true, insertable = true)
#JsonBackReference
public Person getPerson() {
return person;
}
My service class:
#POST
#Path("/PersonRegistration")
#Consumes(MediaType.APPLICATION_JSON)
public Response postPersonCars(Person person) throws Exception{
Session session = null;
ObjectMapper mapper = new ObjectMapper();
//Person per = new Person();
//Car cars = new Car();
try{
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
//per.setCars(person.getCars());
session.save(person);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
throw e;
}finally{
if(null != session){
session.close();
}
}
return Response.status(201).entity(mapper.writeValueAsString(person)).build();
}
This annotation:
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="person")
has two consequences:
mappedBy implies that Car is the owning side of the relationship. This means that whenever you want to establish a relationship between Car and Person, you need to do it by setting the Car.person property to the appropriate value. Changes to Person.cars will be ignored by Hibernate.
cascade=CascadeType.ALL means that whenever you save a Person, Hibernate will also invoke the save operation on all entities contained in Person.cars
Result: you are calling Session.save() on a bunch of Car entities that do not have the Car.person property set properly.
Solution: either change the owning side of the relationship (be aware that you will also need a #JoinColumn on Person.cars if you do not want an extra database table to be created) or loop through Person.cars and set the Car.person property properly in each of them.
cascade=CascadeType.ALL suggests the first solution fits your use case better.

Hibernate insert with join and foreign key

I have some problem with insert in hibernate.
Suppose I have 2 entity
#Entity
public class User{
#Id
#GeneratedValue
int user_id;
String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "utente_id")
list<City> cities;
}
#Entity
public class City{
int user_id
int city_id
}
if I try a create class User and add a list of city but when I try to save, receive this error:
Caused by: java.sql.SQLException: Foreign key constraint violation occurred
this because user_id in class City must be equal at user_id in User, but hibernate first inserts and then updates.
How do i revolve this?
Try first to persist the User object to DB.
Only after you persist you can get the generated value of user_id.
Then you can create the City object, set the user_id field, and persist it.

Can't delete parent without a child in Hibernate

I have two objects User and Workorder. One user can have multiple work orders. The problem is when I delete user it also deletes assigned work orders to that user. I have tried to set my work orders foreign keys to NULL before deleting the user but it still deletes all the associated work orders with that user. I'd like to delete user without deleting the work order assigned to user. What am I missing or doing wrong?
Here's is my User class:
#OneToMany(fetch = FetchType.LAZY, mappedBy="user", orphanRemoval=true)
private Set<WorkOrder> workOrder;
WorkOrder class:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="user_id", nullable = true)
private User user;
UserDAOImpl class:
#Override
public void deleteUser(int theId) {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// delete object with primary key
User user = currentSession.get(User.class, theId);
Set workorders = user.getWorkOrder();
Iterator<WorkOrder> work = workorders.iterator();
while (work.hasNext()){
WorkOrder workorder = work.next();
workorder.setUser(null);
}
currentSession.remove(user);
}
Remove that 'orphanRemoval=true' and check there's no 'cascade' on Workorder.user (if the relation is bidirectional)

Hibernate save object (one to many relationship) foreign key is null

I have one to many relationships between person class and car class. A person can own many cars and vice versa. I am using restful API to post data. My annotations and Get service is working fine but my post service throws " java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL" error whenever I try to insert new data. Child table foreign key is being inserted as null.
Here is part of my code.
Person.java
private List<Car> cars = new ArrayList<Car>();
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="person")
#JsonManagedReference
public List<Car> getCars() {
return cars;
}
Car.java
private Person person;
#ManyToOne
#JoinColumn(name = "PERSON_ID", nullable = false, updatable = true, insertable = true)
#JsonBackReference
public Person getPerson() {
return person;
}
My service class:
#POST
#Path("/PersonRegistration")
#Consumes(MediaType.APPLICATION_JSON)
public Response postPersonCars(Person person) throws Exception{
Session session = null;
ObjectMapper mapper = new ObjectMapper();
//Person per = new Person();
//Car cars = new Car();
try{
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
//per.setCars(person.getCars());
session.save(person);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
throw e;
}finally{
if(null != session){
session.close();
}
}
return Response.status(201).entity(mapper.writeValueAsString(person)).build();
}
This annotation:
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="person")
has two consequences:
mappedBy implies that Car is the owning side of the relationship. This means that whenever you want to establish a relationship between Car and Person, you need to do it by setting the Car.person property to the appropriate value. Changes to Person.cars will be ignored by Hibernate.
cascade=CascadeType.ALL means that whenever you save a Person, Hibernate will also invoke the save operation on all entities contained in Person.cars
Result: you are calling Session.save() on a bunch of Car entities that do not have the Car.person property set properly.
Solution: either change the owning side of the relationship (be aware that you will also need a #JoinColumn on Person.cars if you do not want an extra database table to be created) or loop through Person.cars and set the Car.person property properly in each of them.
cascade=CascadeType.ALL suggests the first solution fits your use case better.

deleting entity in a onetomany relationship

I'm having a problem deleting a child entity item. Everytime I delete it nothing happens and the association between the parent and the child is still there. I've searched through the net and some people suggest using orphanremoval but I've tried it and it didn't work. Appreciate if any could advise.
My codes as below:
ClientProfile Entity (PARENT)
Collapse | Copy Code
#Entity (name="ClientProfile")
public class ClientProfile implements Serializable {
#OneToMany(orphanRemoval = true)
private List<Address> address;
#OneToMany(orphanRemoval = true)
private List<ClientJob> clientJob;
#OneToMany(orphanRemoval = true)
private List<Asset> clientAsset;
...
}
Asset Entity (CHILD)
is a uni-directional relationship so asset entity doesnt contain any #ManyToOne
In my SQL Database table my relationship is CLIENTPROFILE_CLIENTASSET
adn they are connected by the clientid to the assetid
In my session bean this is my remove method:
#Override
public void removeAsset(Long assetId) throws DoesNotExistsException{
Query query = em.createQuery("SELECT as FROM Asset as WHERE as.assetId = :assetid");
query.setParameter("assetid", assetId);
if (query.getResultList().isEmpty()){
throw new DoesNotExistsException("Asset does not exist!");
} else {
em.remove(query.getSingleResult());
}
}
the assetid is being parsed into from the managedbean.
I'm not sure if the remove method is wrong because this is the method I used to remove other entities items without relationship.
This should help you. It is along the same lines. I usually utilize Hibernate instead of JPA to get automatic deletion through cascade attributes.
JPA OneToMany not deleting child

Categories

Resources