JPA #ManyToOne does not working - jpa

I can't understand where I'm going wrong when saving a List within and JPA Entity.
I have a super class Person. Client class extends Person. Client class has a list of Phone entities as #OneToMany (Bidirection) as code shown below. Whenever a Client entity is persisted with that phone list, all phones in list are saved as well. However, in Phone Table there are no client id recorded.
#Entity#Inheritance(strategy=InheritanceType.SINGLE_TABLE)#DiscriminatorColum(name="type")
public abstract class Person implements Serializable {
private static final long serialVersionUID = 1L;
#Id #GeneratedValue(strategy=GenerationType.SEQUENCE,generator="PERSON_SEQ")
#SequenceGenerator(name="PERSON_SEQ",sequenceName="PERSON_SEQ", allocationSize=1,initialValue=1000)
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}}
Client.class
public class Client extends Person implements Serializable {
private static final long serialVersionUID = 1L;
private String foo;
#OneToMany(cascade=CascadeType.ALL,mappedBy="owner")
private List<Phone> phones;
public List<Phone> getPhones() {
return phones;
}
public void setPhones(List<Phone> phones) {
this.phones = phones;
}
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
Phone class
public class Phone implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idPhone;
private String number;
#ManyToOne(fetch=FetchType.EAGER) #JoinColumn(name="id")
private Person owner;
public Long getIdPhone() {
return idPhone;
}
public void setIdPhone(Long idPhone) {
this.idPhone = idPhone;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Person getOwner() {
return owner;
}
public void setOwner(Person owner) {
this.owner = owner;
}
}
ClientController class
#Named(value = "clientController")
#ViewScoped
public class ClientController extends BaseController implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Inject
private ClientService service;
#Inject
private Client client;
#Inject
private Employee employee;
#Inject
private Phone phone;
public void save(ActionEvent event) {
System.out.println(" Saving in Controller");
try {
client = new Client();
employee = new Employee();
Phone p1 = new Phone();
p1.setNumber("99998888");
Phone p2 = new Phone();
p2.setNumber("88887777");
List<Phone> phones = new ArrayList<Phone>();
phones.add(p1);
phones.add(p2);
client.setName("Novembro" );
client.setPhones(phones);
employee.setPhones(phones);
client.setFoo("foo value" );
employee.setBar("bar value");
service.saveOrUpdate(client);
//client = new Client();
addMessage(FacesMessage.SEVERITY_INFO, "Cliente registrado com sucesso");
} catch (Exception e) {
addMessage(FacesMessage.SEVERITY_ERROR, "Tente mais tarde");
e.printStackTrace();
}
}
}
Client Service class
public class ClientService implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Inject
private ClientDAO dao;
public Client saveOrUpdate(Client client) {
System.out.println(" Saving in Service");
return dao.save(client);
}
}
DAO save method
public T save(T entity) {
beginTransaction();
em.persist(entity);
em.flush();
commitAndCloseTransaction();
return entity;
}
I can't understand why it is not working as expected. I mean, save phones entities with ID from Client who owns the phones.
Database Postgresql 9.6
EclipseLink 2.6.0
JPA 2.1
All classes have #Entity and #Discrimator annotations
#Entity
#DiscriminatorValue(value="C")
#Entity
#Table(name="PHONE")

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);
}
}

Add data to database adding data to join tables

I'm working in a project and I'm looking to add data to the database, to two join tables.
My parent:
package entity;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the artiste database table.
*
*/
#Entity
#NamedQuery(name="Artiste.findAll", query="SELECT a FROM Artiste a")
public class Artiste implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_artiste")
private int idArtiste;
#Column(name="a_category")
private String aCategory;
#Column(name="a_name")
private String aName;
private String date;
//bi-directional many-to-one association to Seat
#ManyToOne
#JoinColumn(name="id_seat")
private Seat seat;
public Artiste() {
}
public int getIdArtiste() {
return this.idArtiste;
}
public void setIdArtiste(int idArtiste) {
this.idArtiste = idArtiste;
}
public String getACategory() {
return this.aCategory;
}
public void setACategory(String aCategory) {
this.aCategory = aCategory;
}
public String getAName() {
return this.aName;
}
public void setAName(String aName) {
this.aName = aName;
}
public String getDate() {
return this.date;
}
public void setDate(String date) {
this.date = date;
}
public Seat getSeat() {
return this.seat;
}
public void setSeat(Seat seat) {
this.seat = seat;
}
}
My child:
package entity;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the seat database table.
*
*/
#Entity
#NamedQuery(name="Seat.findAll", query="SELECT s FROM Seat s")
public class Seat implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_seat")
private int idSeat;
private String seat_CA;
private String seat_CB;
private String seat_CC;
private String seat_CD;
//bi-directional many-to-one association to Artiste
#OneToMany(mappedBy="seat")
private List<Artiste> artistes;
public Seat() {
}
public int getIdSeat() {
return this.idSeat;
}
public void setIdSeat(int idSeat) {
this.idSeat = idSeat;
}
public String getSeat_CA() {
return this.seat_CA;
}
public void setSeat_CA(String seat_CA) {
this.seat_CA = seat_CA;
}
public String getSeat_CB() {
return this.seat_CB;
}
public void setSeat_CB(String seat_CB) {
this.seat_CB = seat_CB;
}
public String getSeat_CC() {
return this.seat_CC;
}
public void setSeat_CC(String seat_CC) {
this.seat_CC = seat_CC;
}
public String getSeat_CD() {
return this.seat_CD;
}
public void setSeat_CD(String seat_CD) {
this.seat_CD = seat_CD;
}
public List<Artiste> getArtistes() {
return this.artistes;
}
public void setArtistes(List<Artiste> artistes) {
this.artistes = artistes;
}
public Artiste addArtiste(Artiste artiste) {
getArtistes().add(artiste);
artiste.setSeat(this);
return artiste;
}
public Artiste removeArtiste(Artiste artiste) {
getArtistes().remove(artiste);
artiste.setSeat(null);
return artiste;
}
}
My client:
Artiste a= new Artiste();
Seat b = new Seat();
b.setSeat_CA(request.getParameter("w"));
b.setSeat_CB(request.getParameter("x"));
b.setSeat_CD(request.getParameter("y"));
b.setSeat_CC(request.getParameter("z"));
a.setIdArtiste(b.getIdSeat());
seatFacade.create(b);
a.setAName(request.getParameter("a_name"));
a.setACategory(request.getParameter("a_category"));
a.setDate(request.getParameter("date"));
artisteFacade.create(a);
And I create the FACADE for each one.
Now I can add data but i need also the program add the FOREIGN KEY.
You don't need to get the foreign key, JPA is do every thing, so you should just make it in the right way, so you entities should look like this:
Artiste Entity
#ManyToOne
#JoinColumn(name="id_seat")
private Seat seat;
Seat Entity
#OneToMany(mappedBy="seat", cascade = CascadeType.ALL)
private List<Artiste> artistes = new ArrayList<>();
Your code should look like this:
Artiste a= new Artiste();
Seat b = new Seat();
b.setSeat_CA(request.getParameter("w"));
b.setSeat_CB(request.getParameter("x"));
b.setSeat_CD(request.getParameter("y"));
b.setSeat_CC(request.getParameter("z"));
a.setAName(request.getParameter("a_name"));
a.setACategory(request.getParameter("a_category"));
a.setDate(request.getParameter("date"));
//add this the Article to the list of Seat like this.
b.getArtistes().add(a);
//a.setIdArtiste(b.getIdSeat()); you don't need this
//artisteFacade.create(a); you dont need this also
//set the Seal to your article
a.setSeat(b);
seatFacade.create(b);
So when you persist the Seat the list of articles will persist automaticlly.
This will help you.
You can learn more here : JPA #ManyToOne with CascadeType.ALL

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