Hibernate (JPA) - Weird update for no reason - java

I have an application which accesses an oracle-db which is storing contacts in a table. create, read and update is working fine. But delete won't work only sometimes for some weird reason.
When i start my application, i load all current contacts from my db and put them in a javafx-table. i let hibernate show me all it's sql and thats all it did until here. It only did once a select. Now if i directly start to delete contacts it works fine for 3-4 contacts and then i get an error which tells me, that hibernate tried to run an update-statement where it used as id null. why is hibernate doing this?
this is total nonsense. i double and tripple checked it and there is no db-action running between the select statement and the deletes. why does hibernate do an update in the middle of nowhere without any reason when i tell it to delete?
Here you see all coude and information you can possibly need to understand my situation
public void refresh() {
List<OrganisationContact> allContacts = EntityStore.ORGA_CON_REPO
.readAllWithDetails();
contactTable.getItems().setAll(allContacts);
}
This is the method in my repository
#Override
public List<OrganisationContact> readAllWithDetails() {
try {
JPAJinqStream<Contact> stream = getStreamForTable(Contact.class);
List<OrganisationContact> organisationContactList = new ArrayList<OrganisationContact>();
try {
stream.forEach(con -> organisationContactList
.add(new OrganisationContact(con)));
} catch (javax.persistence.PersistenceException exception) {
NoReplyFromDatabaseException.showErrorDialog();
throw new NoReplyFromDatabaseException(exception);
}
stream.close();
return organisationContactList;
} catch (javax.persistence.PersistenceException exception) {
NoReplyFromDatabaseException.showErrorDialog();
throw new NoReplyFromDatabaseException(exception);
}
}
This is the method in my abstract repository my normal repository is using
protected <TableEntity>JPAJinqStream<TableEntity> getStreamForTable(final Class<TableEntity> pEntityClass) {
if (this.manager != null && this.factory != null && this.provider != null) {
if (this.manager.isOpen() && this.factory.isOpen()) {
return this.provider.streamAll(this.manager, pEntityClass);
}
}
return null;
}
manager is an instance of EntityMananger
factory is an instance of EntityManagerFactory
provider is an instance of JinqJPAStreamProvider
This is the code which is executed when you delete a contact
#FXML
public void onDelete() {
EntityStore.ORGA_CON_REPO.delete(EntityStore.CURRENT_CONTACT);
if (!UnitOfWork.closeTransaction(EntityStore.ORGA_CON_REPO, true)) {
// error occured
}
// ignore that stuff
EntityStore.CURRENT_CONTACT = null;
ModeManager.clearMode();
ModeManager.refreshTable();
}
ORGA_CON_REPO is my repository from above
UnitOfWork knows all existing repositories (in this case only 1 exists) and handles it's transactions
This is my UnitOfWork class
public final class UnitOfWork {
private static final Map<AbstractRepository<?>, EntityManager> units = new HashMap<AbstractRepository<?>, EntityManager>();
private UnitOfWork() {
}
/* PUBLIC */
/**
* Executes a commit/rollback and closes the transaction for the passed
* repository.
*
* #param pRepository
* The repository the transaction belongs to.
* #param pCommit
* If this parameter is <code>true</code>, the transaction will
* be commited before closing. If it is <code>false</code>, the
* transaction will be rolled back before closing.
* #return true if the transaction has been closed successfully, false if an error occured while closing or the manager was null
*/
public synchronized static boolean closeTransaction(
final AbstractRepository<?> pRepository, final boolean pCommit) {
EntityManager manager = units.get(pRepository);
if (manager != null) {
try {
EntityTransaction t = manager.getTransaction();
if (t.isActive()) {
if (pCommit) {
t.commit();
} else {
t.rollback();
}
}
units.remove(pRepository);
return true;
} catch (PersistenceException pException) {
pRepository.resetManager(false);
units.remove(pRepository);
// TODO: log and throw
}
}
return false;
}
/* PROTECTED */
/**
* Starts a new transaction in a new unit of work.
*
* #param pRepository
* The repository the transaction belongs to.
* #param pManager
* The EntityManager of the passed repository.
* #return <code>true</code> if the transaction has been started
* successfully, <code>false</code> if the manager is closed or one
* of the parameters is null.
*/
protected synchronized static boolean beginTransaction(
final AbstractRepository<?> pRepository,
final EntityManager pManager) {
if (pRepository != null || pManager != null) {
if (pManager.isOpen()) {
if (!units.containsKey(pRepository)) {
EntityTransaction t = pManager.getTransaction();
if (!t.isActive()) {
t.begin();
}
units.put(pRepository, pManager);
}
return true;
}
}
return false;
}
}
This is the delete method of my repository
#Override
public boolean delete(OrganisationContact pEntity) {
Contact contactEntity = pEntity.getContact();
return remove(contactEntity);
}
which is using the method of my abstract repository
protected boolean remove(final Object pEntity) {
if (this.canManagerExecute(pEntity)) {
if (this.beginTransaction()) {
this.manager.remove(pEntity);
return true;
}
}
return false;
}
private boolean canManagerExecute(final Object pEntity) {
if (this.manager != null && pEntity != null) {
return this.manager.isOpen();
}
return false;
}
which is using hibernate.
And this are my entities
#Entity
#Table(schema = "reskonverw")
public class Contact {
#Column(name = "phonenumber")
private String phoneNumber;
#Column(name = "firstname")
private String firstName;
#Column(name = "surname")
private String surname;
#Column(name = "email")
private String email;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name="id")
private int id;
#ManyToOne(cascade = CascadeType.ALL)
private Organisation organisation;
#ManyToOne(cascade = CascadeType.ALL)
private Role role;
public Contact() {
}
public Contact(String phoneNumber, String firstName, String surname,
String email, Organisation organisation, Role role) {
this.phoneNumber = phoneNumber;
this.firstName = firstName;
this.surname = surname;
this.email = email;
this.organisation = organisation;
this.role = role;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Organisation getOrganisation() {
return organisation;
}
public void setRole(final Role pRole) {
role = pRole;
}
public Role getRole() {
return role;
}
public void setOrganisation(Organisation organisation) {
this.organisation = organisation;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Override
public String toString() {
return new StringBuilder(surname).append(", ").append(firstName)
.toString();
}
}
#Entity
#Table(schema = "reskonverw")
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
private String name;
public Country() {
}
public Country(String cName) {
this.name = cName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
#Entity
#Table(schema = "reskonverw")
public class Organisation {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
private String name;
private String zipcode;
private String housenumber;
private String city;
private String street;
#ManyToOne(cascade = CascadeType.ALL)
private Country country;
public Organisation() {
}
public Organisation(String name, String zipcode, String housenumber,
String city, String street, Country country) {
this.name = name;
this.zipcode = zipcode;
this.housenumber = housenumber;
this.city = city;
this.street = street;
this.country = country;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getHousenumber() {
return housenumber;
}
public void setHousenumber(String housenumber) {
this.housenumber = housenumber;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
#Override
public String toString() {
return name;
}
}
#Entity
#Table(schema = "reskonverw")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
private String description;
public Role() {
}
public Role(String rDescription) {
this.description = rDescription;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return description;
}
}
My session bean which is used to be displayed in the javafx table
public class OrganisationContact {
private Contact contact;
public OrganisationContact(Contact contact) {
this.contact = contact;
}
/* Entities */
public Organisation getOrganisation() {
return contact.getOrganisation();
}
public void setOrganisation(Organisation organisation) {
contact.setOrganisation(organisation);
}
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public Role getRole() {
return contact.getRole();
}
public void setRole(final Role pRole) {
contact.setRole(pRole);
}
public Country getCountry() {
return contact.getOrganisation().getCountry();
}
public void setCountry(final Country pCountry) {
contact.getOrganisation().setCountry(pCountry);
}
/* EntityStats */
// Organisation
public String getOrganisationName() {
return contact.getOrganisation().getName();
}
public void setOrganisationName(final String pName) {
contact.getOrganisation().setName(pName);
}
public String getOrganisationZipcode() {
return contact.getOrganisation().getZipcode();
}
public void setOrganisationZipcode(final String pZipcode) {
contact.getOrganisation().setZipcode(pZipcode);
}
public String getOrganisationHousenumber() {
return contact.getOrganisation().getHousenumber();
}
public void setOrganisationHouseNumber(final String pHouseNumber) {
contact.getOrganisation().setHousenumber(pHouseNumber);
}
public String getOrganisationCity() {
return contact.getOrganisation().getCity();
}
public void setOrganisationCity(final String pCity) {
contact.getOrganisation().setCity(pCity);
}
public String getOrganisationStreet() {
return contact.getOrganisation().getStreet();
}
public void setOrganisationStreet(final String pStreet) {
contact.getOrganisation().setStreet(pStreet);
}
// Contact
public String getFirstName() {
return contact.getFirstName();
}
public void setFirstName(final String pFirstName) {
contact.setFirstName(pFirstName);
}
public String getSurname() {
return contact.getSurname();
}
public void setSurname(final String pSurname) {
contact.setSurname(pSurname);
}
public String getEmail() {
return contact.getEmail();
}
public void setEmail(final String pEmail) {
contact.setEmail(pEmail);
}
public String getPhoneNumber() {
return contact.getPhoneNumber();
}
public void setPhoneNumber(final String pPhoneNumber) {
contact.setPhoneNumber(pPhoneNumber);
}
// Country
public String getOrganisationCountryName() {
return contact.getOrganisation().getCountry().getName();
}
// Role
public String getRoleDescription() {
return contact.getRole().getDescription();
}
public void setRoleDescription(final String pDescription) {
contact.getRole().setDescription(pDescription);
}
}
EDIT: Here the sql hibernate prints on my console first when it does the select at the programmstart:
Hibernate:
select
*
from
( select
contact0_.id as id1_0_,
contact0_.email as email2_0_,
contact0_.firstname as firstname3_0_,
contact0_.organisation_id as organisation_id6_0_,
contact0_.phonenumber as phonenumber4_0_,
contact0_.role_id as role_id7_0_,
contact0_.surname as surname5_0_
from
reskonverw.Contact contact0_ )
where
rownum <= ?
Hibernate:
select
organisati0_.id as id1_2_0_,
organisati0_.city as city2_2_0_,
organisati0_.country_id as country_id7_2_0_,
organisati0_.housenumber as housenumber3_2_0_,
organisati0_.name as name4_2_0_,
organisati0_.street as street5_2_0_,
organisati0_.zipcode as zipcode6_2_0_,
country1_.id as id1_1_1_,
country1_.name as name2_1_1_
from
reskonverw.Organisation organisati0_
left outer join
reskonverw.Country country1_
on organisati0_.country_id=country1_.id
where
organisati0_.id=?
Hibernate:
select
role0_.id as id1_3_0_,
role0_.description as description2_3_0_
from
reskonverw.Role role0_
where
role0_.id=?
Here the sql hibernate prints on my console when it does the delete at the buttonclick (select because i update all entities afterwards because there are multiple clients):
Hibernate:
delete
from
reskonverw.Contact
where
id=?
Hibernate:
select
*
from
( select
contact0_.id as id1_0_,
contact0_.email as email2_0_,
contact0_.firstname as firstname3_0_,
contact0_.organisation_id as organisation_id6_0_,
contact0_.phonenumber as phonenumber4_0_,
contact0_.role_id as role_id7_0_,
contact0_.surname as surname5_0_
from
reskonverw.Contact contact0_ )
where
rownum <= ?
Here the sql hibernate prints on my console when it does an update instead of a delete at the buttonclick (no select because it crashes before):
Hibernate:
update
reskonverw.Contact
set
email=?,
firstname=?,
organisation_id=?,
phonenumber=?,
role_id=?,
surname=?
where
id=?
Jul 08, 2015 8:05:12 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1407, SQLState: 72000
Jul 08, 2015 8:05:12 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: ORA-01407: Aktualisieren von ("RESKONVERW"."CONTACT"."ORGANISATION_ID") zu NULL nicht möglich
For not german ppl, 'ERROR: ORA-01407: Aktualisieren von ("RESKONVERW"."CONTACT"."ORGANISATION_ID") zu NULL nicht möglich' means 'error - setting resconverw.contact.organisation_id to null not possible

Contact has a foreginkey to Organisation. It is linked by the id of the Organisation. When i delete the Contact, Hibernate sometimes tries to set the foreginkey to null before deleting it. Not always for some reason i couldn't figure out yet. In my db i had setup a constraint which prevent the foregin key from becomeing null. And that is why the update failed and i got an exception. I removed the constraint and since then it is working.
Thanks all for the help

Related

org.springframework.orm.jpa.JpaSystemException: Error accessing field by reflection for persistent property

I am using Spring Boot (v 2.4.0) with Hibernate 5.4.24 and, when trying to get some information from my database, I keep getting this error message:
org.springframework.orm.jpa.JpaSystemException: Error accessing field [private int es.uc3m.orders.model.Shoppingcart.usID] by reflection for persistent property [es.uc3m.orders.model.Shoppingcart#usID] : 1; nested exception is org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private int es.uc3m.orders.model.Shoppingcart.usID] by reflection for persistent property [es.uc3m.orders.model.Shoppingcart#usID] : 1
It is kind of weird for me, because it only happens when I try to access the table Shoppingcart, since I can get informatin from the rest of the tables.
I also used the exact same entities with another project but, insetad of using Spring Boot, persistence was made with EntityManagers and it worked perfectly fine.
These are my entities:
Shoppingcart
#Entity
#NamedQuery(name="Shoppingcart.findAll", query="SELECT s FROM Shoppingcart s")
public class Shoppingcart implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int scID;
private int usID;
//bi-directional many-to-many association to Product
#ManyToMany
#JoinTable(
name="sc_has_product"
, joinColumns={
#JoinColumn(name="scID")
}
, inverseJoinColumns={
#JoinColumn(name="productID")
}
)
private List<Product> products;
//bi-directional one-to-one association to User
#OneToOne(mappedBy="shoppingcart")
private User user;
public Shoppingcart() {
}
public int getScID() {
return this.scID;
}
public void setScID(int scID) {
this.scID = scID;
}
public int getusID() {
return this.usID;
}
public void setusID(int usID) {
this.usID = usID;
}
public List<Product> getProducts() {
return this.products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
public boolean isNull() {
return getProducts().isEmpty();
}
User
#Entity
#Table(name="users")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String address;
#Column(name="card_n")
private Long cardN;
private String city;
private String country;
private int cvv;
private String email;
private String exp;
private String name;
private String pass;
private String surname1;
private String surname2;
private String typeOfUser;
#Column(name="zip_code")
private int zipCode;
//bi-directional many-to-one association to Order
#OneToMany(mappedBy="user")
private List<Orders> orders;
//bi-directional many-to-one association to Product
#OneToMany(mappedBy="user")
private List<Product> products;
//bi-directional one-to-one association to Shoppingcart
#OneToOne(cascade=CascadeType.REMOVE)
#JoinColumn(name="ID", referencedColumnName="usID", insertable=false, updatable=false)
private Shoppingcart shoppingcart;
public User() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public Long getCardN() {
return this.cardN;
}
public void setCardN(Long cardN) {
this.cardN = cardN;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return this.country;
}
public void setCountry(String country) {
this.country = country;
}
public int getCvv() {
return this.cvv;
}
public void setCvv(int cvv) {
this.cvv = cvv;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getExp() {
return this.exp;
}
public void setExp(String exp) {
this.exp = exp;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPass() {
return this.pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getSurname1() {
return this.surname1;
}
public void setSurname1(String surname1) {
this.surname1 = surname1;
}
public String getSurname2() {
return this.surname2;
}
public void setSurname2(String surname2) {
this.surname2 = surname2;
}
public int getZipCode() {
return this.zipCode;
}
public void setZipCode(int zipCode) {
this.zipCode = zipCode;
}
public List<Orders> getOrders() {
return this.orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
public Orders addOrder(Orders order) {
getOrders().add(order);
order.setUser(this);
return order;
}
public Orders removeOrder(Orders order) {
getOrders().remove(order);
order.setUser(null);
return order;
}
public List<Product> getProducts() {
return this.products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public Product addProduct(Product product) {
getProducts().add(product);
product.setUser(this);
return product;
}
public Product removeProduct(Product product) {
getProducts().remove(product);
product.setUser(null);
return product;
}
public Shoppingcart getShoppingcart() {
return this.shoppingcart;
}
public void setShoppingcart(Shoppingcart shoppingcart) {
this.shoppingcart = shoppingcart;
}
public String getTypeOfUser() {
return typeOfUser;
}
public void setTypeOfUser(String typeOfUser) {
this.typeOfUser = typeOfUser;
}
}
This is the ShoppingcartDAO class:
public interface ShoppingCartDAO extends CrudRepository<Shoppingcart, Integer> {
#Query("SELECT s FROM Shoppingcart s JOIN User u ON u.id = s.usID AND u.id LIKE :id")
Shoppingcart findByUser(#Param("id") int id);
#Query("SELECT s FROM Shoppingcart s")
List<Shoppingcart> findAllShoppingCart();
}
And, finally, this is my ShoppingcartController class:
#RestController
#CrossOrigin
#EnableAutoConfiguration
public class ShoppingCartController {
#Autowired
ShoppingCartDAO scDAO;
#RequestMapping(value = "sc", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<?> assignShoppingCart(#RequestBody(required = true) Shoppingcart sc) {
try {
scDAO.save(sc);
return new ResponseEntity<Void>(HttpStatus.CREATED);
} catch(Exception e) {
return new ResponseEntity<Void>(HttpStatus.BAD_REQUEST);
}
}
#RequestMapping(value = "sc", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<?> getEveryShoppingCart() {
try {
List<Shoppingcart> sc = scDAO.findAllShoppingCart();
return new ResponseEntity<List<Shoppingcart>>(sc, (sc != null) ? HttpStatus.OK : HttpStatus.NOT_FOUND);
} catch(Exception e) {
System.out.println(e);
return new ResponseEntity<Void>(HttpStatus.BAD_REQUEST);
}
}
}
I am really going nuts as I can´t figure out what is going on with my code, so thank you in advance if you help me.
I finally fixed it. For those of you who are wondering how, I deleted the relationships between tables that I had, ending with:
Shoppingcart:
#Entity
public class Shoppingcart implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int scID;
#Column(name = "usID")
private Integer userID;
public Shoppingcart() {
}
public int getScID() {
return this.scID;
}
public void setScID(int scID) {
this.scID = scID;
}
public Integer getUserID() {
return userID;
}
public void setUserID(Integer userID) {
this.userID = userID;
}
Product:
#Entity
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int productID;
private String category;
private String color;
private String description;
private String estadoProducto;
private String fecha;
private int orderID;
private String photo;
private double price;
private int seller;
private String sexo;
private String state = "Disponible";
private String talla;
private String title;
public Product() {
}
public int getProductID() {
return this.productID;
}
public void setProductID(int productID) {
this.productID = productID;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getColor() {
return this.color;
}
public void setColor(String color) {
this.color = color;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getEstadoProducto() {
return this.estadoProducto;
}
public void setEstadoProducto(String estadoProducto) {
this.estadoProducto = estadoProducto;
}
public String getFecha() {
return this.fecha;
}
public void setFecha(String fecha) {
this.fecha = fecha;
}
public String getPhoto() {
return this.photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
public double getPrice() {
return this.price;
}
public void setPrice(double price) {
this.price = price;
}
public String getSexo() {
return this.sexo;
}
public void setSexo(String sexo) {
this.sexo = sexo;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public String getTalla() {
return this.talla;
}
public void setTalla(String talla) {
this.talla = talla;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public int getOrderID() {
return orderID;
}
public void setOrderID(int orderID) {
this.orderID = orderID;
}
public int getSeller() {
return seller;
}
public void setSeller(int seller) {
this.seller = seller;
}
With this, everything worked fine, but don't ask me why, because I don't know it.
Your Getters/Setters are wrongly implemented.
Like :
Actual :
public int getusID() {
return this.usID;
}
Expected :
public int getUsID() {
return this.usID;
}
Same with setter

Hibernate OneToOne relationship

I have 3 classes Appointment,Patient and Doctor.Appointment have 1to1 reletionship with both Patient and Doctor.
When i insert a appointment object in database everytime the new patient and doctor object is also inserted in the database.
Patient Class:
#Entity
#Table(name = "Patient")
public class Patient {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int patientId;
private String firstName;
private String lastName;
private int age;
private String cnic;
private String contactNumber;
private String homeNumber;
private String country;
private String city;
private String town;
private String streetNo;
private String houseNo;
private String email;
private String username;
private String password;
public int getPatientId() {
return patientId;
}
public void setPatientId(int patientId) {
this.patientId = patientId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getCnic() {
return cnic;
}
public void setCnic(String cnic) {
this.cnic = cnic;
}
public String getContactNumber() {
return contactNumber;
}
public void setContactNumber(String contactNumber) {
this.contactNumber = contactNumber;
}
public String getHomeNumber() {
return homeNumber;
}
public void setHomeNumber(String homeNumber) {
this.homeNumber = homeNumber;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getTown() {
return town;
}
public void setTown(String town) {
this.town = town;
}
public String getStreetNo() {
return streetNo;
}
public void setStreetNo(String streetNo) {
this.streetNo = streetNo;
}
public String getHouseNo() {
return houseNo;
}
public void setHouseNo(String houseNo) {
this.houseNo = houseNo;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getId(){
return patientId;
}
public Patient getPatient(){
return this;
}
}
Doctor Class :
#Entity
#Table(name = "Doctor")
public class Doctor extends Users {
private String specialization;
public String getSpecialization() {
return specialization;
}
public void setSpecialization(String specialization) {
this.specialization = specialization;
}
}
Appointment Class:
#Entity
public class AppointmentClass {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int appointmentId;
private int appointmentDay;
private int appointmentTime;
#OneToOne (cascade=CascadeType.ALL,fetch = FetchType.EAGER)
private Patient patient;
#OneToOne (cascade=CascadeType.ALL,fetch = FetchType.EAGER)
private Doctor doctor;
public int getAppointmentId() {
return appointmentId;
}
public void setAppointmentId(int appointmentId) {
this.appointmentId = appointmentId;
}
public int getAppointmentDay() {
return appointmentDay;
}
public void setAppointmentDay(int appointmentDay) {
this.appointmentDay = appointmentDay;
}
public int getAppointmentTime() {
return appointmentTime;
}
public void setAppointmentTime(int appointmentTime) {
this.appointmentTime = appointmentTime;
}
public Patient getPatient() {
return patient;
}
public void setPatient(Patient patient) {
this.patient = patient;
}
public Doctor getDoctor() {
return doctor;
}
public void setDoctor(Doctor doctor) {
this.doctor = doctor;
}
}
Service Class:
public class AppointmentPatientService {
private SessionFactory sessionFactory = null;
public AppoinmentPatient createNewAppointment(AppoinmentPatient appointment){
try{
sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Patient patient = new Patient();
Doctor doctor = new Doctor();
patient = (Patient)(appointment).getPatient();
AppointmentClass appointment1 = new AppointmentClass();
appointment1 = (AppointmentClass)(appointment).getAppointment();
doctor = (Doctor)appointment.getDoctor();
appointment1.setPatient(patient);
appointment1.setDoctor(doctor);
session.beginTransaction();
session.save(appointment1);
session.getTransaction().commit();
session.close();
}catch(Exception ex){
ex.printStackTrace();
}
return appointment;
}
}
Is there any way that when i save the appointment object the new objects of patient and doctor not save to the database.
I shall be thankful :)
I think your relationship type should not be OneToOne from neither the doctor or the patient, because one doctor can have many appointments and one patient can have many appointments. So it should be OneToMany from both sides, in which case a new doctor and a new patient won't be created for each new appointment if you supply the appointment with correct existing doctor and patient ID-s.
In the class AppointmentClass, change the cascade settings.
You can use cascade=CascadeType.NONE, This will make sure that the associated Patient and Doctor objects are not saved to database.
You can see all other values of CascadeType to find the right choice for you.

Caused by: java.sql.SQLSyntaxErrorException: ORA-01722: invalid number in JPA HIBERNATE HQL

Having this class
#Entity
public class PriorityAreaKeyword {
public enum PriorityAreaKey {
ALL ("ALL", "ALL DEVICES"),
IOS ("IOS", "IOS"),
ANDROID ("ANDROID","ANDROID");
private final String name;
private final String id;
private PriorityAreaKey(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
}
#Id
private Long id;
#Column(name = "key")
#Enumerated(EnumType.STRING)
private PriorityAreaKey key;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public PriorityAreaKey getKey() {
return key;
}
public void setKey(PriorityAreaKey key) {
this.key = key;
}
public List<PriorityArea> getPriorityAreas() {
return priorityAreas;
}
public void setPriorityAreas(List<PriorityArea> priorityAreas) {
this.priorityAreas = priorityAreas;
}
}
I have in the DAO this method that is working fine:
#Override
#SuppressWarnings("unchecked")
public Set<PriorityArea> findPriorityAreas(PriorityAreaKey key) {
String jpql = "from PriorityAreaKeyword as pak where pak.key = :key";
Query query = entityManager.createQuery(jpql);
query.setParameter("key", key);
List<PriorityArea> priorityAreas = query.getResultList();
return new HashSet<PriorityArea>(priorityAreas);
}
I created a view like this v_report_beneficiary_list (id, email, priority_area_key)
/**
*
*/
#Entity
#Table(name = "v_report_beneficiary_list")
public class ReportBeneficiaryItem {
private Long id;
private String email;
private PriorityAreaKey priorityAreaKey;
/**
* #return the id
*/
#Id
public Long getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
#Column(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name = "priority_area_key")
public PriorityAreaKey getPriorityAreaKey() {
return priorityAreaKey;
}
public void setPriorityAreaKey(PriorityAreaKey priorityAreaKey) {
this.priorityAreaKey = priorityAreaKey;
}
In the DAO I've created another method like this:
#Su
ppressWarnings("unchecked")
#Override
public List<ReportBeneficiaryItem> findReportProposalXBeneficiary(ProposalExportFilter filter) {
// Create basic query
String jpql = "from " + ReportBeneficiaryItem.class.getName() + " b where b.priorityAreaKey = :key ";
// Create and execute jpa query
Query query = createQuery(jpql);
query.setParameter("key", filter.getPriorityAreaKey());
return query.getResultList();
}
That throws me a throws me an Exception Caused By: java.sql.SQLSyntaxErrorException: ORA-01722: invalid number
You are missing #Enumerated(EnumType.STRING) on ReportBeneficiaryItem#getPriorityAreaKey() as you have on PriorityAreaKeyword#key, so it's expecting numbers (enum index) in the database for that field, but finds strings
#Column(name = "priority_area_key")
#Enumerated(EnumType.STRING)
public PriorityAreaKey getPriorityAreaKey() {
return priorityAreaKey;
}

Found two representations of same collection hibernate exception

I have a Spring MVC application that handle Users and Structures that can hosts one or more User.
I'm using Hibernate for the persistence and I'm having some issues with the One-To-Many relation between User and Structure.
This is my User model:
#Entity
#Table(name="USERS")
public class User extends DatabaseEntity {
#Id #GeneratedValue
private Long id = 0L;
#Column
#NotEmpty
private String firstName;
#Column
private String lastName;
#Column
private Date birthDate;
#Column
private String nation;
#Column
private String town;
#Column
private String idNumber;
#Column(unique = true)
private String email;
#Column String resetPasswordToken = "";
#Column
private String password;
#Column
private String avatarUrl;
#Column #Enumerated(EnumType.STRING)
private Role role;
#ManyToOne
#JoinColumn(name = "STRUCTURE_ID")
#Cascade({CascadeType.DETACH})
private Structure structure;
public enum Role {
ADMINISTRATOR,
SPECIALIST,
PATIENT,
DOCTOR,
CARE_GIVER
}
public User() {
birthDate = new Date();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getNation() {
return nation;
}
public void setNation(String nation) {
this.nation = nation;
}
public String getTown() {
return town;
}
public void setTown(String town) {
this.town = town;
}
public String getIdNumber() {
return idNumber;
}
public void setIdNumber(String idNumber) {
this.idNumber = idNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAvatarUrl() {
return avatarUrl;
}
public void setAvatarUrl(String avatarUrl) {
this.avatarUrl = avatarUrl;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public Set<Group> getGroups() {
return null;
}
public void setGroups(Set<Group> groups) {
}
public Set<Group> getCreatedGroups() {
return null;
}
public void setCreatedGroups(Set<Group> createdGroups) {
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<HangoutUser> getHangoutUsers() {
return null;
}
public void setHangoutUsers(Set<HangoutUser> hangoutUsers) {
}
public String getResetPasswordToken() {
return resetPasswordToken;
}
public void setResetPasswordToken(String resetPasswordToken) {
this.resetPasswordToken = resetPasswordToken;
}
public Group getStructure() {
return structure;
}
public void setStructure(Structure structure) {
this.structure = structure;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
if (!email.equals(user.email)) return false;
if (!id.equals(user.id)) return false;
return true;
}
#Override
public int hashCode() {
Long res = id;
if(id == null)
res = 0L;
int result = res.hashCode();
result = 31 * result + email.hashCode();
return result;
}
}
And this is my Structure model:
#Entity
#Table(name = "STRUCTURES")
public class Structure extends DatabaseEntity {
#Id #GeneratedValue
Long id = 0L;
#Column
String name;
#Column
String address;
#Column
String city;
#Column
String state;
#OneToMany(mappedBy = "structure", fetch = FetchType.EAGER)
#Cascade({CascadeType.DELETE})
Set<User> users = new HashSet<User>();
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;
}
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address;
}
public String getCity()
{
return city;
}
public void setCity(String city)
{
this.city = city;
}
public String getState()
{
return state;
}
public void setState(String state)
{
this.state = state;
}
public Set<User> getUsers()
{
return this.users;
}
public void setUsers(Set<User> users)
{
this.users = users;
}
}
My issue is that when I try to find all the Users with the value STRUCTURE_ID evaluated, I get an Hibernate Exception, like this:
org.springframework.orm.hibernate3.HibernateSystemException: Found two representations of same collection: it.amtservices.livinglab.model.Group.users; nested exception is org.hibernate.HibernateException: Found two representations of same collection: it.amtservices.livinglab.model.Structure.users
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:690) ...
What should I do to solve this problem? I have already tried many ways but nothing solved.
I paste the abstract repository implementation for the UsersRepository and StructureRepository:
#Transactional
public abstract class AbstractRepository<Model extends DatabaseEntity>
{
Logger logger = Logger.getLogger(this.getClass().getSimpleName());
#PersistenceContext
EntityManager em;
protected Class<Model> ModelClass;
protected List<Model> findBy(String parameterName, Object parameterValue)
{
Query q = em.createQuery("select t from " + ModelClass.getSimpleName() + " t where t." + parameterName + " = :" + parameterName);
q.setParameter(parameterName, parameterValue);
List<Model> results = null;
try
{
results = q.getResultList();
}
catch (Exception e)
{
return null;
}
return results;
}
protected List<Model> findBy(Map<String, Object> parameters)
{
String whereClause = "";
for (String key : parameters.keySet())
{
if (!whereClause.equals("")) whereClause += " and ";
whereClause += "t." + key + " = :" + key;
}
Query q = null;
try
{
q = em.createQuery("select t from " + ModelClass.getSimpleName() + " t where " + whereClause);
}
catch (Exception e)
{
e.printStackTrace();
}
for (String key : parameters.keySet())
{
q.setParameter(key, parameters.get(key));
}
List<Model> results = null;
try
{
results = q.getResultList();
}
catch (Exception e)
{
return null;
}
return results;
}
protected Model findOneBy(String parameterName, Object parameterValue)
{
List<Model> results = findBy(parameterName, parameterValue);
if (results != null && results.size() > 0) return results.get(0);
return null;
}
protected Model findOneBy(Map<String, Object> parameters)
{
List<Model> results = findBy(parameters);
if (results != null && results.size() > 0) return results.get(0);
return null;
}
public Model findOne(Long id)
{
return findOneBy("id", id);
}
public List<Model> findAll()
{
Query q = em.createQuery("select t from " + ModelClass.getSimpleName() + " t");
List<Model> results = null;
try
{
results = q.getResultList();
}
catch (Exception e)
{
return null;
}
return results;
}
public boolean save(Model model)
{
try
{
Model newModel = em.merge(model);
if (model.getId() == 0L) model.setId(newModel.getId());
}
catch (Exception e)
{
logger.error(ModelClass.getSimpleName() + "Repository: " + e.getMessage());
return false;
}
return true;
}
public void save(List<Model> models)
{
for (Model model : models)
{
save(model);
}
}
public void delete(Model model)
{
delete(model.getId());
}
public void delete(Long id)
{
beforeDelete(findOne(id));
try
{
Query q = em.createQuery("delete from " + ModelClass.getSimpleName() + " t where t.id = :id").setParameter("id", id);
q.executeUpdate();
}
catch (Exception e)
{
logger.error(ModelClass.getSimpleName() + "Repository: " + e.getMessage());
}
}
public void delete(Collection<Model> models)
{
for (Model model : models)
{
delete(model.getId());
}
}
public void deleteAll()
{
for (Model model : findAll())
{
delete(model);
}
}
public abstract void beforeDelete(Model model);
public List<Model> find(List<Long> ids)
{
List<Model> models = new ArrayList<Model>();
for (Long id : ids)
{
Model model = findOne(id);
if (model != null) models.add(model);
}
return models;
}
}
Thank you!

Strange mysql retrieve with hibernate criteria

In a web-service i have the following function which retreives some infos of a doctor and his patient based on patient's phone:
public String findDoctorOfPatient(String phone) {
AnnotationConfiguration config = new AnnotationConfiguration();
config.configure("hibernate.cfg.xml");
SessionFactory factory = config.buildSessionFactory();
Session session = factory.openSession();
session.beginTransaction();
Criteria query = session.createCriteria(doctor.class);
query.createCriteria("patients", "p");
query.add(Restrictions.eq("p.phone", phone));
List<doctor> doctorList = (ArrayList<doctor>) query.list();
session.getTransaction().commit();
String answear = "";
for (doctor d : doctorList) {
answear = answear.concat("docPhone" + d.getPhone() + "docEmail"
+ d.getEmail() + "patDia"
+ d.getPatients().iterator().next().getDiastolic()
+ "patSys"
+ d.getPatients().iterator().next().getSystolic());
}
if (doctorList.isEmpty()) {
session.close();
factory.close();
return "No Doctor!";
} else {
session.close();
factory.close();
return answear;
}
}
The problem is when i have one patient is ok , but when i add second patient it gives me the details of last patient despite i have set to criteria tha firt's patient phone!
I have 2 tables:
1.doctor(id,username,password,phone,email)
2.patient(id,name,surname,phone,systolic,diastolic,doctorid(FK refers to doctor.id))
I have configured properly the hibernate.cfg.xml.
And i have set the class for doctor and patient:
#Entity
public class doctor {
#Id
private int id;
private String username;
private String password;
private String phone;
private String email;
#OneToMany(targetEntity = patient.class, cascade = CascadeType.ALL, mappedBy = "doctor")
#Cascade(value = org.hibernate.annotations.CascadeType.ALL)
private Collection<patient> patients = new ArrayList<patient>();
public Collection<patient> getPatients() {
return patients;
}
public void setPatients(Collection<patient> patients) {
this.patients = patients;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
#Entity
public class patient {
#Id
private int id;
private String name;
private String surname;
private String phone;
private int systolic;
private int diastolic;
#ManyToOne
private doctor doctor;
public doctor getDoctor() {
return doctor;
}
public void setDoctor(doctor doctor) {
this.doctor = doctor;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public int getSystolic() {
return systolic;
}
public void setSystolic(int systolic) {
this.systolic = systolic;
}
public int getDiastolic() {
return diastolic;
}
public void setDiastolic(int diastolic) {
this.diastolic = diastolic;
}
}
In this web-service the response is always the same (given the mobile number) .
It gives me always the patSys=130 and patDia=80 which are the second's patient info!.Something must be wrong in the webservice but to me all seems ok!
You need to create Criteria object on Patient and no need to obtain transaction here.
Criteria query = session.createCriteria(Patient.class)
.add(Restrictions.eq("phone", phone));
List<Patient> patList = (ArrayList<Patient>) query.list();
String result="";
if(!patList.isEmpty()) {
Patient patient=patList.get(0);
result="Doc Phone : " + patient.getDoctor().getPhone();
}
return result;

Categories