How to use #IdClass annotation with composite key - jpa

Someone could please share an example of two entities working on a Master-Detail pattern for EclipseLink (JPA 2.1) using composite key with #IdClass

Here is the example from the documentation
public class EmployeePK implements Serializable {
private long empId;
private long department;
public EmployeePK() {
}
public long getEmpId() {
return this.empId;
}
public void setEmpId(long empId) {
this.empId = empId;
}
public long getDepartment() {
return this.department;
}
public void setDepartment(long department) {
this.department = department;
}
public int hashCode() {
return (int)this.empId.hashCode();
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof EmployeePK)) return false;
EmployeePK pk = (EmployeePK) obj;
return pk.empId.equals(this.empId) && pk.department.equals(this.department);
}
}
and
#IdClass(EmployeePK.class)
#Entity
public class Employee implements Serializable{
#Id
long empId;
#Id
#ManyToOne
Department department;
...
}

Related

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.

Could not create stateless EJB with JPA

I'm trying to insert some data to DB with EJB and JPA. When I execute the code i got the serverError: class javax.faces.el.EvaluationException javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB error. Here my code. I have try lot of by changing various things. what is that error occurred? I think my Entity manager initialization has some wrong
DesignationEntity de = new DesignationEntity();
de.setDesignationName(this.designationName);
de.setDesignationDescription(this.designationDescription);
ds.addDesignationDb(de);
EJB service class
#Stateless
#LocalBean
public class DesignationService {
#PersistenceUnit(unitName = "ecs2complainmanager")
private EntityManager em;
public DesignationService() {
}
public void addDesignationDb(DesignationEntity de){
em.persist(de);
}
}
Entity class
#Entity
public class DesignationEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Integer designationId;
private String designationName;
private String designationDescription;
#OneToOne(mappedBy = "designationId")
private UserEntity user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getDesignationId() {
return designationId;
}
public void setDesignationId(Integer designationId) {
this.designationId = designationId;
}
public String getDesignationName() {
return designationName;
}
public void setDesignationName(String designationName) {
this.designationName = designationName;
}
public String getDesignationDescription() {
return designationDescription;
}
public void setDesignationDescription(String designationDescription) {
this.designationDescription = designationDescription;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
}
#PersistenceUnit is the cause. After I changed it to #PersistenceContext

AnnotationException: mappedBy reference an unknown target entity property

I have one exception, which yold what I have no mapping on table. But I have this
Exeption is : \
AnnotationException: mappedBy reference an unknown target entity property: Relative.people in Person.relations
Relative entity is here:
#Entity
#Table(name = "relation")
public class Relative extends AbstractModel<UUID> implements Model<UUID> {
private UUID id;
private Person person;
private RelationTypeEnum relation;
public Relative() {
}
#Override
public void assignId() {
id = UUID.randomUUID();
}
#Override
#Id
#Column(name = "id")
public UUID getId() {
return id;
}
#ManyToOne
#JoinColumn(name="person_id", nullable=false)
public Person getPerson() {
return person;
}
#Column(name = "relation")
public RelationTypeEnum getRelation() {
return relation;
}
public void setId(UUID id) {
this.id = id;
}
public void setPerson(Person person) {
this.person = person;
}
public void setRelation(RelationTypeEnum relation) {
this.relation = relation;
}
}
And Person entity is here:
#Entity
#Table(name = "people")
public class Person extends AbstractModel<UUID> implements Model<UUID> {
private UUID id;
private String name;
private List<Relative> relations;
#Override
public void assignId() {
id = UUID.randomUUID();
}
#Override
#Id
#Column(name = "id")
public UUID getId() {
return id;
}
#Column(name = "name")
public String getName() {
return name;
}
#OneToMany(targetEntity=Relative.class, cascade=CascadeType.ALL,
mappedBy="people")
public List<Relative> getRelations() {
return relations;
}
public void setId(UUID id) {
this.id = id;
}
public void setName(String username) {
this.name = username;
}
public void setRelations(List<Relative> relations) {
this.relations = relations;
}
}
Solved.
Just changed
#Table(name = "people")
to
#Table(name = "person")
In my case there was a project which included a copy of the jar causing this issue. It was a web project which is including the jar inside its lib i.e. 2 copies of the same jar one with a different class version. Only discovered this when I physically opened the main ear and found the 2nd jar inside a web project.

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.
}