Spring Boot JPA Bulk insert - jpa

I have 3 Entities Parent,Child,SubChild. Parent is a parent of Child and Child is a parent of SubChild. I need to insert around 700 objects of Parent. Parent can have 50 Objects of Child. Child can have 50 objects of SubChild.
I tried normal repository.save(ListOfObjects) it takes approx 4mins.
Then I tried using entity manager's persist, flush and clear based on batch size(500). This also took approx 4 mins.
There wasn't much difference in performance. Please suggest a best way to insert such a high amount of data efficiently.
Parent
#Entity
public class Parent {
#Id #GeneratedValue(strategy= GenerationType.AUTO)
private Long parentId;
private String aaa;
private String bbb;
private String ccc;
#Version
private Long version;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "parent", fetch = FetchType.LAZY)
#JoinColumnsOrFormulas({
#JoinColumnOrFormula(column=#JoinColumn(name="parentId",referencedColumnName="parentId",nullable=false))})
private List<Child> childs = new ArrayList<>();
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public String getAaa() {
return aaa;
}
public void setAaa(String aaa) {
this.aaa = aaa;
}
public String getBbb() {
return bbb;
}
public void setBbb(String bbb) {
this.bbb = bbb;
}
public String getCcc() {
return ccc;
}
public void setCcc(String ccc) {
this.ccc = ccc;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public List<Child> getChilds() {
return childs;
}
public void setChilds(List<Child> childs) {
this.childs = childs;
}
}
Child
#Entity
public class Child {
#Id #GeneratedValue(strategy= GenerationType.AUTO)
private Long childId;
private String ddd;
private String ccc;
private Integer eee;
#OneToMany(cascade = CascadeType.ALL,orphanRemoval = true, mappedBy = "child", fetch = FetchType.LAZY)
#JoinColumnsOrFormulas({
#JoinColumnOrFormula(column = #JoinColumn(name = "childId", referencedColumnName = "childId", nullable = false)) })
private List<SubChild> subChilds = new ArrayList<>();
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumnsOrFormulas({
#JoinColumnOrFormula(column= #JoinColumn( name="parentId",referencedColumnName="parentId",nullable=false))
})
private Parent parent;
public Long getChildId() {
return childId;
}
public void setChildId(Long childId) {
this.childId = childId;
}
public String getDdd() {
return ddd;
}
public void setDdd(String ddd) {
this.ddd = ddd;
}
public String getCcc() {
return ccc;
}
public void setCcc(String ccc) {
this.ccc = ccc;
}
public Integer getEee() {
return eee;
}
public void setEee(Integer eee) {
this.eee = eee;
}
public List<SubChild> getSubChilds() {
return subChilds;
}
public void setSubChilds(List<SubChild> subChilds) {
this.subChilds = subChilds;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
SubChild
#Entity
public class SubChild {
#Id #GeneratedValue(strategy= GenerationType.AUTO)
private Long subChildId;
private String fff;
private String ggg;
private Integer hhh;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumnsOrFormulas({
#JoinColumnOrFormula(column= #JoinColumn( name="childId",referencedColumnName="childId",nullable=false))
})
private Child child;
public Long getSubChildId() {
return subChildId;
}
public void setSubChildId(Long subChildId) {
this.subChildId = subChildId;
}
public String getFff() {
return fff;
}
public void setFff(String fff) {
this.fff = fff;
}
public String getGgg() {
return ggg;
}
public void setGgg(String ggg) {
this.ggg = ggg;
}
public Integer getHhh() {
return hhh;
}
public void setHhh(Integer hhh) {
this.hhh = hhh;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
}
Repository method used for persisting the list of Parent Entity
#Value("${spring.jpa.hibernate.jdbc.batch_size}")
private int batchSize;
public <T extends Parent> Collection<T> bulkSave(Collection<T> entities) {
final List<T> savedEntities = new ArrayList<T>(entities.size());
int i = 0;
for (T t : entities) {
savedEntities.add(persistOrMerge(t));
i++;
if (i % batchSize == 0) {
// Flush a batch of inserts and release memory.
entityManager.flush();
entityManager.clear();
}
}
return savedEntities;
}
private <T extends Parent> T persistOrMerge(T t) {
if (t.getTimeSlotId() == null) {
entityManager.persist(t);
return t;
} else {
return entityManager.merge(t);
}
}
application.yml
spring:
application:
name: sample-service
jpa:
database: MYSQL
show-sql: true
hibernate:
ddl-auto: update
dialect: org.hibernate.dialect.MySQL5Dialect
naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
jdbc:
batch_size: 100
jackson:
date-format: dd/MM/yyyy
thymeleaf:
cache: false
spring.datasource.url : jdbc:mysql://${dbhost}/sample?createDatabaseIfNotExist=true
spring.datasource.username : root
spring.datasource.password : root
spring.datasource.driver-class-name : com.mysql.cj.jdbc.Driver

To enable batch insert you need the batch_size property which you have in your configuration.
Also since a jdbc batch can target one table only you need the spring.jpa.hibernate.order_inserts=true property to order the insert between parent and child or else the statement are unordered and you will see a partial batch (new batch anytime an insert in a different table is called)

Related

Spring Data JPA. Parent table data is not getting rolled back when exception occurred while inserting record in child table

I have 2 tables one to many relationship between Employee and Department table, Employee table are having column Id as PK, Name and Sal whereas Department table having column Dept_ID,Dept_Name & Dept_Loc and primary key is (Dept_ID,Dept_Name) i.e composite key and Dept_ID is foreign key ref from Employee table's Id column. The issue is when I save record in parent table i.e Employee it get saved but if in case I get exception while inserting record for child table i.e Department table,,data is not getting rolled back for EMployee table. Please help I m struggling and I am attaching my code.
public class GlEmployee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "emp_seq")
#Column(name = "EMP_ID")
private long empId;
#Column(name = "EMP_CITY")
private String empCity;
#Column(name = "EMP_NAME")
private String empName;
#Column(name = "EMP_SALARY")
private BigDecimal empSalary;
// bi-directional many-to-one association to EmpDepartment
#OneToMany(mappedBy = "glEmployee",cascade = CascadeType.ALL)
private List<EmpDepartment> empDepartments = new ArrayList<>();
public GlEmployee() {
}
public long getEmpId() {
return this.empId;
}
public void setEmpId(long empId) {
this.empId = empId;
}
public String getEmpCity() {
return this.empCity;
}
public void setEmpCity(String empCity) {
this.empCity = empCity;
}
public String getEmpName() {
return this.empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public BigDecimal getEmpSalary() {
return this.empSalary;
}
public void setEmpSalary(BigDecimal empSalary) {
this.empSalary = empSalary;
}
public List<EmpDepartment> getEmpDepartments() {
return this.empDepartments;
}
public void setEmpDepartments(List<EmpDepartment> empDepartments) {
this.empDepartments = empDepartments;
}
public EmpDepartment addEmpDepartment(EmpDepartment empDepartment) {
getEmpDepartments().add(empDepartment);
empDepartment.setGlEmployee(this);
return empDepartment;
}
public EmpDepartment removeEmpDepartment(EmpDepartment empDepartment) {
getEmpDepartments().remove(empDepartment);
empDepartment.setGlEmployee(null);
return empDepartment;
}
}
#Entity
#Table(name = "EMP_DEPARTMENT")
public class EmpDepartment implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private EmpDepartmentPK id;
#Column(name = "DEP_LOC")
private String depLoc;
public EmpDepartment(EmpDepartment id, String dep) {
}
// bi-directional many-to-one association to GlEmployee
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "DEP_ID", insertable = false, updatable = false)
private GlEmployee glEmployee;
public EmpDepartment() {
}
public EmpDepartmentPK getId() {
return this.id;
}
public void setId(GlEmployee glEmployee, String deptName) {
EmpDepartmentPK empDepartment = new
EmpDepartmentPK(glEmployee.getEmpId(), deptName);
this.id = empDepartment;
}
public String getDepLoc() {
return this.depLoc;
}
public void setDepLoc(String depLoc) {
this.depLoc = depLoc;
}
public GlEmployee getGlEmployee() {
return this.glEmployee;
}
public void setGlEmployee(GlEmployee glEmployee) {
this.glEmployee = glEmployee;
}
}
#Embeddable
public class EmpDepartmentPK implements Serializable {
// default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#Column(name = "DEP_ID")
private long depId;
#Column(name = "DEP_NAME")
private String depName;
public EmpDepartmentPK() {
}
public EmpDepartmentPK(long depId, String depName) {
super();
this.depId = depId;
this.depName = depName;
}
public long getDepId() {
return this.depId;
}
public void setDepId(long depId) {
this.depId = depId;
}
public String getDepName() {
return this.depName;
}
public void setDepName(String depName) {
this.depName = depName;
}
#Service
public class EmployeeService {
#Autowired
private EmployeeRepository employeeRepository;
#Transactional
public void createEmp() {
GlEmployee employee = new GlEmployee();
employee.setEmpCity("Pune");
employee.setEmpName("Ankush");
employee.setEmpSalary(new BigDecimal(200));
employeeRepository.save(employee);
EmpDepartment department = new EmpDepartment();
department.setId(employee, "ME");
department.setDepLoc(null);
department.setGlEmployee(employee);
employee.addEmpDepartment(department);
employeeRepository.save(employee);
}
}

JPA OneToOne cascade delete

i have a rellationship between 2 classes Document and Medecin
#Entity
public class Document implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String annee;
private Date dateVisite;
private String secteur;
private String typeVisite;
#OneToOne( fetch=FetchType.LAZY,cascade=CascadeType.REMOVE)
#JoinColumn(name = "idMedecin")
private Medecin medecin;
public Document(String annee,
Date dateVisite, String secteur, String typeVisite) {
super();
this.annee = annee;
this.dateVisite = dateVisite;
this.secteur = secteur;
this.typeVisite = typeVisite;
}
public String getSecteur() {
return secteur;
}
public void setSecteur(String secteur) {
this.secteur = secteur;
}
public String getTypeVisite() {
return typeVisite;
}
public void setTypeVisite(String typeVisite) {
this.typeVisite = typeVisite;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAnnee() {
return annee;
}
public void setAnnee(String annee) {
this.annee = annee;
}
public Date getDateVisite() {
return dateVisite;
}
public void setDateVisite(Date dateVisite) {
this.dateVisite = dateVisite;
}
}
and the medecin entity is
#Entity
public class Medecin implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String nom;
private String secteur;
private int telephone;
private int specialite;
public Medecin() {
super();
// TODO Auto-generated constructor stub
}
public Medecin(String nom, String secteur, int telephone, int specialite) {
super();
this.nom = nom;
this.secteur = secteur;
this.telephone = telephone;
this.specialite = specialite;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getSecteur() {
return secteur;
}
public void setSecteur(String secteur) {
this.secteur = secteur;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
public int getSpecialite() {
return specialite;
}
public void setSpecialite(int specialite) {
this.specialite = specialite;
}
}
the problem is that after i generate the database i want if i delete the document record from the database i want the medecin record will be deleted also but in my case if i delete the document record the medecin record dont be deleted
Based on your configuration, Hibernate will generate Document table with foreign key pointing to Medicine table.
To achieve your requirement, it should be like:
public class Document {
#OneToOne(mappedBy = "document", cascade = CascadeType.REMOVE)
private Medicine medicine;
}
public class Medicine {
#OneToOne
private Document document;
}
Updated
public void delete(int id){
Document document = entityManager.find(Document.class, id);
entityManager.remove(document);
entityManager.flush();
}

Delete a record using Spring data jpa

I have an entity 'Competence', this entity has OneToMany relation with two other entities : CandidatCompetence and OffreCompetence, and a ManyToOne relation with GroupCompetence.
And I have a rest delete service with will take the id of a Competence entity as following :
#Secured("ROLE_ADMIN")
#RequestMapping(value="/competences/{id}",method= RequestMethod.DELETE)
public void deleteCompetence(#PathVariable Long id) {
competenceMetier.deleteCompetence(id);
}
Then the deleteCompetence function will call a delete function from the Competence Repository which extends JpaRepository<Competence, Long> as following :
public void deleteCompetence(Long id) {
competenceRepository.delete(id);
}
The problem is that when I call the rest delete method, I get 200 as an http response, but nothing in the body, the same for the log I can't see the DELETE sql query anywhere, and the entity still exists in the database.
here are my entities :
Competence :
#Entity
public class Competence implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long codeCompetence;
private String titre;
private Boolean activated = true;
#OneToMany(mappedBy="competence",cascade = CascadeType.ALL)
private Collection<CandidatCompetence> candidatCompetences;
#OneToMany(mappedBy="competence",cascade = CascadeType.ALL)
private Collection<OffreCompetence> offreCompetences;
#ManyToOne
#JoinColumn(name = "groupCompetence")
private GroupCompetence groupCompetence;
public Long getCodeCompetence() {
return codeCompetence;
}
public void setCodeCompetence(Long codeCompetence) {
this.codeCompetence = codeCompetence;
}
public String getTitre() {
return titre;
}
public void setTitre(String titre) {
this.titre = titre;
}
#JsonIgnore
#XmlTransient
public Collection<CandidatCompetence> getCandidatCompetences() {
return candidatCompetences;
}
#JsonSetter
public void setCandidatCompetences(Collection<CandidatCompetence> candidatCompetences) {
this.candidatCompetences = candidatCompetences;
}
#JsonIgnore
#XmlTransient
public Collection<OffreCompetence> getOffreCompetences() {
return offreCompetences;
}
public void setOffreCompetences(Collection<OffreCompetence> offreCompetences) {
this.offreCompetences = offreCompetences;
}
public Competence(String titre) {
super();
this.titre = titre;
}
public Competence() {
super();
// TODO Auto-generated constructor stub
}
#JsonIgnore
#XmlTransient
public GroupCompetence getGroupCompetence() {
return groupCompetence;
}
#JsonSetter
public void setGroupCompetence(GroupCompetence groupCompetence) {
this.groupCompetence = groupCompetence;
}
public Boolean getActivated() {
return activated;
}
public void setActivated(Boolean activated) {
this.activated = activated;
}
}
OffreCompetence :
#Entity
public class OffreCompetence implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long codeOffreCompetence;
private String niveauRequis;
#ManyToOne
#JoinColumn(name = "competence")
private Competence competence;
#ManyToOne
#JoinColumn(name="offre")
private Offre offre;
public Long getCodeOffreCompetence() {
return codeOffreCompetence;
}
public void setCodeOffreCompetence(Long codeOffreCompetence) {
this.codeOffreCompetence = codeOffreCompetence;
}
public String getNiveauRequis() {
return niveauRequis;
}
public void setNiveauRequis(String niveauRequis) {
this.niveauRequis = niveauRequis;
}
public Competence getCompetence() {
return competence;
}
public void setCompetence(Competence competence) {
this.competence = competence;
}
#JsonIgnore
public Offre getOffre() {
return offre;
}
#JsonSetter
public void setOffre(Offre offre) {
this.offre = offre;
}
public OffreCompetence(String niveauRequis) {
super();
this.niveauRequis = niveauRequis;
}
public OffreCompetence() {
super();
// TODO Auto-generated constructor stub
}
}
CandidatCompetence :
#Entity
public class CandidatCompetence implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long codeCandidatCompetence;
private String niveauExperience;
#ManyToOne
#JoinColumn(name = "candidat")
private Candidat candidat;
#ManyToOne
#JoinColumn(name = "competence")
private Competence competence;
public Long getCodeCandidatCompetence() {
return codeCandidatCompetence;
}
public void setCodeCandidatCompetence(Long codeCandidatCompetence) {
this.codeCandidatCompetence = codeCandidatCompetence;
}
public String getNiveauExperience() {
return niveauExperience;
}
public void setNiveauExperience(String niveauExperience) {
this.niveauExperience = niveauExperience;
}
public Candidat getCandidat() {
return candidat;
}
public void setCandidat(Candidat candidat) {
this.candidat = candidat;
}
public Competence getCompetence() {
return competence;
}
public void setCompetence(Competence competence) {
this.competence = competence;
}
public CandidatCompetence(String niveauExperience) {
super();
this.niveauExperience = niveauExperience;
}
public CandidatCompetence() {
super();
// TODO Auto-generated constructor stub
}
}
GroupCompetence :
#Entity
public class GroupCompetence implements Serializable {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long codeGroupCompetence;
private String titre;
private Boolean activated = true;
#OneToMany(mappedBy="groupCompetence",cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Collection<Competence> competences;
public Long getCodeGroupCompetence() {
return codeGroupCompetence;
}
public void setCodeGroupCompetence(Long codeGroupCompetence) {
this.codeGroupCompetence = codeGroupCompetence;
}
public String getTitre() {
return titre;
}
public void setTitre(String titre) {
this.titre = titre;
}
public GroupCompetence(String titre) {
this.titre = titre;
}
public GroupCompetence() {
}
public Boolean getActivated() {
return activated;
}
public void setActivated(Boolean activated) {
this.activated = activated;
}
public Collection<Competence> getCompetences() {
return competences;
}
public void setCompetences(Collection<Competence> competences) {
this.competences = competences;
}
}
You should annotate your Service Method deleteCompetence with #Transactional.

Entity Manager: em.merge() creates a new record instead of updating

I was developing an EJB application using netbeans which manages Hotel Bookings. I realised that the em.merge() function of the Entity manager inserts a new record in the database instead of updating if the primary key or the #Id of the entity is set to autogenerated.
I have two entities - Booking and Room. The ID for Booking is autogenerated whereas for Room its not autogenerated. The same merge() function in the session bean inserts a new row for Booking but updates for Room.
My Entity beans and session beans are as follows:-
Booking Entity
#SequenceGenerator(name="booking_seq", initialValue=1, allocationSize=100)
#Entity
#NamedQueries({#NamedQuery(name="Booking.getAll",query="SELECT e FROM Booking e order by e.bookingId")})
public class Booking implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="booking_seq")
#Column
private int bookingId;
#Column
private int roomId;
#Column
private int customerId;
#Column
#Temporal(javax.persistence.TemporalType.DATE)
private Date arrival_date;
#Column
#Temporal(javax.persistence.TemporalType.DATE)
private Date departure_date;
public Booking(int bookingId, int roomId, int customerId, Date arrival_date, Date departure_date) {
this.bookingId = bookingId;
this.roomId = roomId;
this.customerId = customerId;
this.arrival_date = arrival_date;
this.departure_date = departure_date;
}
public Booking() {
}
public int getBookingId() {
return bookingId;
}
public void setBookingId(int bookingId) {
this.bookingId = bookingId;
}
public int getRoomId() {
return roomId;
}
public void setRoomId(int roomId) {
this.roomId = roomId;
}
public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
public Date getArrival_date() {
return arrival_date;
}
public void setArrival_date(Date arrival_date) {
this.arrival_date = arrival_date;
}
public Date getDeparture_date() {
return departure_date;
}
public void setDeparture_date(Date departure_date) {
this.departure_date = departure_date;
}
}
Room Entity
#Entity
#Table
#NamedQueries({#NamedQuery(name="Room.getAll",query="SELECT e FROM Room e order by e.roomId")})
public class Room implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private int roomId;
#Column
private String roomType;
#Column
private String bedType;
#Column
private double tariff;
public Room() {
}
public Room(int roomId, String roomType, String bedType, double tariff) {
this.roomId = roomId;
this.roomType = roomType;
this.bedType = bedType;
this.tariff = tariff;
}
public int getRoomId() {
return roomId;
}
public void setRoomId(int roomId) {
this.roomId = roomId;
}
public String getRoomType() {
return roomType;
}
public void setRoomType(String roomType) {
this.roomType = roomType;
}
public String getBedType() {
return bedType;
}
public void setBedType(String bedType) {
this.bedType = bedType;
}
public double getTariff() {
return tariff;
}
public void setTariff(double tariff) {
this.tariff = tariff;
}
}
The session bean for Booking Entity
#Stateless
public class BookingDAO implements BookingDAOLocal {
#PersistenceContext
private EntityManager em;
#Override
public void addBooking(Booking booking) {
em.persist(booking);
}
#Override
public void editBooking(Booking booking) {
em.merge(booking);
}
#Override
public void deleteBooking(int bookingId) {
em.remove(em.find(Booking.class, bookingId));
}
}
The session bean for Room Entity
#Stateless
public class RoomDAO implements RoomDAOLocal {
#PersistenceContext
private EntityManager em;
#Override
public void addRoom(Room room) {
em.merge(room);
em.flush();
}
#Override
public void editRoom(Room room) {
em.merge(room);
em.flush();
}
#Override
public void deleteRoom(int roomId) {
em.remove(em.find(Room.class, roomId));
}
}
Actually i got the answer now. For the editBooking() method i was using the same code as addBooking(). In addBooking() i didnt have the setBookingId() method call as it was autogenerated. Just needed to add the extra part for edit method.
else if ("Add".equalsIgnoreCase(action) || "Edit".equalsIgnoreCase(action) )
{
try {
arrival_date = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(request.getParameter("arrival_date"));
departure_date = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(request.getParameter("departure_date"));
}
catch(ParseException e) {
e.printStackTrace();
}
Booking booking = new Booking();
if("Edit".equalsIgnoreCase(action))
{
int bookingId=Integer.parseInt(request.getParameter("bookingId"));
booking.setBookingId(bookingId);
}
booking.setRoomId(Integer.parseInt(request.getParameter("roomId")));
booking.setCustomerId(customerId);
booking.setArrival_date(arrival_date);
booking.setDeparture_date(departure_date);
if("Add".equalsIgnoreCase(action))
bookingDao.addBooking(booking);
else
bookingDao.editBooking(booking);
request.setAttribute("allBookings", bookingDao.getAllBookings());
request.getRequestDispatcher("booking_details.jsp").forward(request, response);
}
You are not trying to updating the record, you re trying to persisting the same room instead of try this.
#Override
public void editRoom(Room room) {
Room r-= em.merge(room);
r.setRoomType("2bed"); // your own update field other than the #Id (Primary key)
em.flush();
// you can retun the updated employee.
}

JPA delete a record while updating

Can somebody help me with following scenario?
I have a requirement where I need to delete the membership record and child table when the child is not associated with any other parent record..else I just need to dissociate the membership record.
I'm using JPA Eclipse link...
Below are my three entities.. Please note that Parent and Child are linked via Parent_Child many-to-many relationship. I'm using Parent_Child table on both sides as we have extra columns in it..
//Parent
#Entity
#Table(name = "PARENT")
public class Parent implements java.io.Serializable {
#Id
#Column(name = "parent_id")
private String parentId;
private Set<ParentChild> parentChildSet = new HashSet<ParentChild>(0);
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent")
public Set<ParentChild> getParentChildSet() {
return parentChildSet;
}
public void setParentChildSet(Set<ParentChild> parentChildSet) {
this.parentChildSet = parentChildSet;
}
}
//Child
#Entity
#Table(name = "CHILD")
public class Child implements java.io.Serializable {
private String ChildId;
private Set<ParentChild> parentChildSet = new HashSet<ParentChild>(0);
#Id
#Column(name = "child_id")
public String getChildId() {
return ChildId;
}
public void setChildId(String childId) {
ChildId = childId;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "child")
public Set<ParentChild> getParentChildSet() {
return parentChildSet;
}
public void setParentChildSet(Set<ParentChild> parentChildSet) {
this.parentChildSet = parentChildSet;
}
}
//Parent-Child
#Entity
#Table(name = "PARENT_CHILD")
public class ParentChild implements java.io.Serializable{
private String parentChildId;
private Parent parent;
private Child child;
#Id
#Column(name = "parent_child_id")
public String getParentChildId() {
return parentChildId;
}
public void setParentChildId(String parentChildId) {
this.parentChildId = parentChildId;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
}
Relationships: Parent - Praent_Child (one-to-many)
Child - Parent_Child (one-to-many)
I'm trying it do it as below...but, it gives me integrity constraint exception as i'm deleting the child and then updating the parent
public void ParentChildServiceDAO{
........
.........
if(parentChildSet().size() > 1){
parent.getParentChildSet().remove(parentChildRecord);
child.getParentChildSet().remove(parentChildRecord);
} else{
parent.getParentChildSet().remove(parentChildRecord);
child.getParentChildSet().remove(parentChildRecord);
getJpaTemplate().remove(child);
}
update(parent);
}
Your help is greatly appreciated...