I have a Java EE application with EclipseLink/JPA entities communicating with my PostgreSQL database. Everything seemed to work fine but lately I notice more and more strange behaviours with my entities so I need your help to figure out what settings and/or bits of code are wrong...
I have one main issue :sometimes (that's a bad start), when I delete an object through my web app, the object is well deleted in my database (I see it) but when I refresh the app, the deleted object suddenly re-appears (in the app + in the database !) so I guess there is a problem of managed entities behind this ?!
For example, I have an entity "Project" which has a list of "Analysis" and I got this problem when deleting a analysis from a project. It first gets deleted (also in the DB) but when I reopen the project the analysis reappears !
Here is my class Project :
/**
* The persistent class for the projet database table.
*
*/
#Entity
#Table(name="projet")
public class Projet implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_projet", unique=true, nullable=false)
private Integer idProjet;
#Column(name="nom_projet", nullable=false, length=50)
#OrderAttribute(lang=Language.BOTH)
#ShowParameter(position=10)
#IdentifierName(lang=Language.BOTH)
private String nomProjet;
#Column(name="projet_public", nullable=false)
private Boolean projetPublic;
//bi-directional many-to-one association to Analyse
#OneToMany(mappedBy="projet", cascade={CascadeType.ALL})//orphanRemoval=true,
private Set<Analyse> analyses;
//bi-directional many-to-one association to Utilisateur the creator of the project
#ManyToOne
#JoinColumn(name="id_utilisateur", nullable=false)
#ShowParameter(position=20)
private Utilisateur utilisateur;
//bi-directional many-to-one association to ProjetUtilDroit
#OneToMany(mappedBy="projet", cascade={CascadeType.ALL})
private Set<ProjetUtilDroit> projetUtilDroits;
public Projet() {
}
public Integer getIdProjet() {
return this.idProjet;
}
public void setIdProjet(Integer idProjet) {
this.idProjet = idProjet;
}
public String getNomProjet() {
return this.nomProjet;
}
public void setNomProjet(String nomProjet) {
this.nomProjet = nomProjet;
}
public Boolean getProjetPublic() {
return projetPublic;
}
public void setProjetPublic(Boolean projetPublic) {
this.projetPublic = projetPublic;
}
public Set<Analyse> getAnalyses() {
return this.analyses;
}
public void setAnalyses(Set<Analyse> analyses) {
this.analyses = analyses;
}
public Utilisateur getUtilisateur() {
return this.utilisateur;
}
public void setUtilisateur(Utilisateur utilisateur) {
this.utilisateur = utilisateur;
}
public Set<ProjetUtilDroit> getProjetUtilDroits() {
return this.projetUtilDroits;
}
public void setProjetUtilDroits(Set<ProjetUtilDroit> projetUtilDroits) {
this.projetUtilDroits = projetUtilDroits;
}
#Override
public boolean equals(Object o){
if(o instanceof Projet){
Projet project = (Projet) o;
return (project.idProjet == this.idProjet) || (project.nomProjet.equalsIgnoreCase(this.nomProjet));
}
return false;
}
}
Here is my class Analysis (Analyse in French) :
/**
* The persistent class for the analyz database table.
*
*/
#Entity
#Table(name="analyz")
public class Analyse implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_analyse", unique=true, nullable=false)
private Integer idAnalyse;
#Column(name="nom_analyse", nullable=false, length=50)
#OrderAttribute(lang = Language.BOTH)
private String nomAnalyse;
//bi-directional many-to-one association to Projet
#ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
#JoinColumn(name="id_projet", nullable=false)
private Projet projet;
//bi-directional many-to-one association to Scenario
#OneToMany(mappedBy="analyse", cascade={CascadeType.ALL})//orphanRemoval=true,
private Set<Scenario> scenarios;
public Analyse() {
}
public Integer getIdAnalyse() {
return this.idAnalyse;
}
public void setIdAnalyse(Integer idAnalyse) {
this.idAnalyse = idAnalyse;
}
public String getNomAnalyse() {
return this.nomAnalyse;
}
public void setNomAnalyse(String nomAnalyse) {
this.nomAnalyse = nomAnalyse;
}
public Projet getProjet() {
return this.projet;
}
public void setProjet(Projet projet) {
this.projet = projet;
}
public Set<Scenario> getScenarios() {
return this.scenarios;
}
public void setScenarios(Set<Scenario> scenarios) {
this.scenarios = scenarios;
}
#Override
public boolean equals(Object o){
if(o instanceof Analyse){
Analyse a = (Analyse) o;
return (this.idAnalyse == a.idAnalyse) || (a.getProjet().equals(this.getProjet()) && (this.nomAnalyse.equalsIgnoreCase(a.nomAnalyse)));
}
return false;
}
}
And I coded a generic DAO for all the classical functions like create/update/delete. Here is my code :
public class BasicDAO<T extends Serializable> implements IDao<T> {
/** The entity class. */
private Class<T> entityClass;
/**
* The entity manager factory
*/
protected EntityManagerFactory emf;
/**
* Instantiates a new abstract dao.
*/
public BasicDAO(Class<T> c) {
entityClass = c;
}
/**
* Gets the emf.
*
* #return the emf
*/
public EntityManagerFactory getEmf() {
return emf;
}
/**
* Sets the emf.
*
* #param em the new emf
*/
public void setEmf(EntityManagerFactory emf) {
this.emf = emf;
}
public T findById(Integer id){
T result = null;
EntityManager em = emf.createEntityManager();
if (id == null || id < 1)
throw new PersistenceException("Id may not be null or negative");
result = em.find(entityClass, id);
em.refresh(result);
em.close();
return result;
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public List<T> findAll(){
List<T> result = null;
EntityManager em = emf.createEntityManager();
CriteriaQuery<Object> cq = em.getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
result = (List)em.createQuery(cq).getResultList();
em.close();
return result;
}
public void create(T entity){
System.out.println("Create de AbstractDAO");
//First we check that the object is not alreadt in database
List<T> list = findAll();
if(list.contains(entity)){
return;
}
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
if(entity == null)
throw new PersistenceException("Entity to persist may not be null");//throw Persistence exception
em.persist(entity);
em.getTransaction().commit();
em.close();
}
public void delete(T entity){
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
if (entity == null)
throw new PersistenceException("Entity to delete may not be null");
em.remove(em.merge(entity));
em.getTransaction().commit();
em.close();
}
public T update(T entity){
T result = null;
if (entity == null){
System.out.println("Exception : entity to update may not be null");
throw new PersistenceException("Entity to update may not be null");
}
List<T> list = findAll();
int numberEquals = 0;
for(T elem : list){
if(elem.equals(entity))
numberEquals++;
}
if(numberEquals>1)
return null;
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.merge(entity);
result = entity;
em.getTransaction().commit();
em.close();
return result;
}
}
Any help or critics would be much appreciated ! :-)
Related
Please be so kind to help me understand why, by running attached code, I have multiple records been written in parent table from my data base (MySQL) with corresponding to a record in related table, although the set up in Java code is for one to one relation (i.e. one records in parent corresponding to only one record in other related table.
I am at your disposal for any questions you might have on the subject.
many thank for support
petrisor
public class Main {
public static void main(String[] args) {
createParkingLot();
AddEmployees(1);
AddEmployees(2);
}
public static void createParkingLot(){
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("java2curs4e1PU");
EntityManager em = emf.createEntityManager();
ParkingLot p1= new ParkingLot();
p1.setParking_lot_no(1);
try{
em.getTransaction().begin();
em.persist(p1);
em.getTransaction().commit();
} finally {
em.close();
emf.close();
}
}
public static void AddEmployees(int employee_number){
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("java2curs4e1PU");
EntityManager em = emf.createEntityManager();
ParkingLot p2 = em.find(ParkingLot.class,1);
Employee a1 = new Employee();
a1.setEmployee_name("Employee_name_#"+employee_number);
a1.setParking_lot(p2);
try{
em.getTransaction().begin();
em.persist(a1);
em.getTransaction().commit();
} finally {
em.close();
emf.close();
}
}
}
+++++++++++++++++++++++++++++
related entities description:
+++++++++++++++++++++++++++++
Entity Employee
+++++++++++++++++++++++++++++
#Entity
#Table(name = "employees")
public class Employee implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String employee_name;
#OneToOne(cascade = CascadeType.ALL,optional = false,fetch =
FetchType.LAZY)
#JoinColumn(name = "id_parking_lot")
private ParkingLot parking_lot;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmployee_name() {
return employee_name;
}
public void setEmployee_name(String employee_name) {
this.employee_name = employee_name;
}
public ParkingLot getParking_lot() {
return parking_lot;
}
public void setParking_lot(ParkingLot parking_lot) {
this.parking_lot = parking_lot;
}
#Override
public String toString() {
return "Employee{" + "id=" + id + ", name=" + employee_name + ",
parking lot=" + parking_lot + '}';
}
}
++++++++++++++++++++++++++++
Entity ParkingLot:
++++++++++++++++++++++++++++
#Entity
#Table(name = "parking_lots")
public class ParkingLot implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY )
private int id;
private int parking_lot_no;
#OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY,optional =
false,mappedBy = "parking_lot")
private Employee employee;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getParking_lot_no() {
return parking_lot_no;
}
public void setParking_lot_no(int parking_lot_no) {
this.parking_lot_no = parking_lot_no;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
#Override
public String toString() {
return "ParkingLot{" + "id=" + id + ", parking lot number=" +
parking_lot_no + '}';
}
}
Normally I would expect the program to through an exception as I tried to insert another Employee (Employee_name_#2) with the same parking lot (id 1).
Instead in table employees I found that I have 2 employees with same parking lot.
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")
I created #ManyToMany realtion between Actors(Aktorzy) and Films(Filmy). In one of my function when i call findAll() from films i get this in Glassfish console:
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-6094] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: The parameter name [idAktora] in the query's selection criteria does not match any parameter name defined in the query.
Query: ReadAllQuery(name="aktorzy" referenceClass=Aktorzy sql="SELECT t1.IDAKTORA, t1.IMIE_AKTORA, t1.NAZWISKO_AKTORA FROM aktorzy_filmy t0, AKTORZY t1 WHERE ((t0.idAktora = ?) AND ((t0.idFilmu = ?) AND (t1.IDAKTORA = t0.idAktorzyFilmy)))")
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:480)
and the second in my opinion important part of log:
Caused by: Exception [EclipseLink-6094] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: The parameter name [idAktora] in the query's selection criteria does not match any parameter name defined in the query.
I think that the problem is that the query try to get all actors informations from actors_films(aktorzy_filmy) table but this is only additional table to create ManyToMany relation and it shoult take it from Actors(Aktorzy) but i dont know how to change that.
Here's my code:
ActorDTO (part):
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idAktora;
private String imie_aktora;
private String nazwisko_aktora;
#ManyToMany(mappedBy = "aktorzy")
private List<Film> filmy;
Films (part):
#ManyToMany(fetch= FetchType.EAGER)
#JoinTable(
name="aktorzy_filmy",
joinColumns={
#JoinColumn(name="idFilmu", referencedColumnName="idFilmu"),
#JoinColumn(name="idAktora", referencedColumnName="idAktora")
},
inverseJoinColumns=#JoinColumn(name="idAktorzyFilmy")
)
private List<Aktorzy> aktorzy;
public List<Aktorzy> getAktorzy() {
return aktorzy;
}
public void addAktor(Aktorzy aktor){
this.aktorzy.add(aktor);
aktor.getFilmy().add(this);
}
and where the problem occures here in client app:
case 12: {
System.err.println("Uzupenij obsade filmu");
System.out.println(filmFacade.findAll());
System.out.println("Podaj id filmu ktoremu chcesz nadac obsade");
int idFilmu = odczyt.nextInt();
Film film = filmFacade. find(idFilmu);
System.out.println("Dodajesz obsade do filmu "+ filmFacade.find(idFilmu).toString());
boolean czyMaDodacKolejnegoAktora = true;
List<Integer> dostepni=new ArrayList<Integer>();
while(czyMaDodacKolejnegoAktora){
dostepni.clear();
for(Aktorzy a: aktorzyFacade.findAll()){
if(!film.getAktorzy().contains(a)){
System.out.println(a.toString());
dostepni.add(a.getId());
}
}
System.out.println("Wybierz id aktora ktorego chcesz przypisac do filmu");
System.err.println("0 konczy akcje");
int wyborAktora = odczyt.nextInt();
if(wyborAktora == 0){
czyMaDodacKolejnegoAktora = false;
}
if(dostepni.contains(wyborAktora)){
film.addAktor(aktorzyFacade.find(wyborAktora));
filmFacade.edit(film);
}else{
System.err.println("Nie możesz dodać aktora");
}
}
break;
}
AbstractFacede:
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0] + 1);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
and AktorzyFacade
#Stateless
public class AktorzyFacade extends AbstractFacade<Aktorzy> implements app.dao.AktorzyFacadeRemote {
#PersistenceContext(unitName = "PPProjekt-ejbPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public AktorzyFacade() {
super(Aktorzy.class);
}
}
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.
}
This is in JPA2 (EclipseLink) and JSF2.
I have an entity class Student:
#Entity
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstname;
private String lastname;
private int age;
public Student(String firstname, String lastname, int age) {
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
public Student() {
}
// accessors and mutators here
}
Session bean StudentFacade that inherits AbstractFacade:
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public T edit(T entity) {
return getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
// other methods: findAll, findRange, count
}
#Stateless
public class StudentFacade extends AbstractFacade<Student> {
#PersistenceContext(unitName = "jpa2testsPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public StudentFacade() {
super(Student.class);
}
public boolean contains(Student s) {
return getEntityManager().contains(s);
}
public void testContains() {
Student s = find(1L);
boolean isContains = getEntityManager().contains(s);
}
}
This is my JSF Managed Bean:
#ManagedBean
#RequestScoped
public class IndexController {
#EJB
private StudentFacade studentFacade;
/**
* Creates a new instance of IndexController
*/
public IndexController() {
}
public String test() {
Student s = new Student("John", "Doe", 20);
studentFacade.create(s);
Student s1 = studentFacade.find(1L); // This works because table only has 1 record
boolean isContains = studentFacade.contains(s);
return null;
}
}
When I run test() from managed bean, isContains is false. But when testContains() in StudentFacade is called, isContains is true. Why is this?
StudentFacade is a Stateless Session Bean (SSB). The contents of its instance variables are not guaranteed to be preserved across method calls (reference). It's like having a different instance of EntityManager created for each method invocation.
When you run your test from the managed bean, you invoke two different methods on the SSB, therefore a different EntityManager instance is created for each call, and the second one does not contain the Student instance because it has not been loaded yet.
But when you run your test inside a method of the SSB itself, the same EntityManager is used for the scope of the entire method, therefore the call to contains() returns true.