I am developing a restful ws that one of its methods is to insert some data in a database. The info is passed via Json, and at first I thought that maybe the json was incorrect, buy when I debug the app, the server side is correctly building the object that then i passed to hibernate saveOrUpdate(). This is what happens:
Hibernate: update CargasEnc set Fecha=?, HojaRutaID=?, CargaTipoID=? where CargaEncID=?
Hibernate: update CargasDet set Averiado=?, Cambio=?, Entrega=?, EnvaseID=?, Lleno=?, Retiro=?, Vacio=? where CargaDetID=?
Hibernate: update CargasDet set Averiado=?, Cambio=?, Entrega=?, EnvaseID=?, Lleno=?, Retiro=?, Vacio=? where CargaDetID=?
Hibernate: update CargasDet set Averiado=?, Cambio=?, Entrega=?, EnvaseID=?, Lleno=?, Retiro=?, Vacio=? where CargaDetID=?
Hibernate: update CargasDet set Averiado=?, Cambio=?, Entrega=?, EnvaseID=?, Lleno=?, Retiro=?, Vacio=? where CargaDetID=?
Hibernate: update CargasDet set Averiado=?, Cambio=?, Entrega=?, EnvaseID=?, Lleno=?, Retiro=?, Vacio=? where CargaDetID=?
Hibernate: update CargasDet set Averiado=?, Cambio=?, Entrega=?, EnvaseID=?, Lleno=?, Retiro=?, Vacio=? where CargaDetID=?
Hibernate: update CargasDet set CargaEncID=null where CargaEncID=?
That last line is strange, why is putting cargaEncId null and when i checked with log4j cargaEncId has a value of 1654.
Another thing I tried was to use a test client on the server. I got the same object from the database, changed some items, and the saveOrUpdate() and it worked, and hibernate did all the same sql statements than before except for the last one.
This are my two classes:
package com.designfreed.entities;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "CargasEnc")
public class Carga {
#Id
#GeneratedValue
#Column(name = "CargaEncID")
private Long id;
#Column(name = "Fecha")
private Date fecha;
#ManyToOne
#JoinColumn(name = "CargaTipoID")
private CargaTipo tipo;
#Column(name = "HojaRutaID")
private Long hojaRutaId;
#OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
#JoinColumn(name = "CargaEncID")
private List<ItemCarga> items;
public Carga() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getFecha() {
return fecha;
}
public void setFecha(Date fecha) {
this.fecha = fecha;
}
public CargaTipo getTipo() {
return tipo;
}
public void setTipo(CargaTipo tipo) {
this.tipo = tipo;
}
public Long getHojaRutaId() {
return hojaRutaId;
}
public void setHojaRutaId(Long hojaRutaId) {
this.hojaRutaId = hojaRutaId;
}
public List<ItemCarga> getItems() {
return items;
}
public void setItems(List<ItemCarga> items) {
this.items = items;
}
#Override
public String toString() {
return "Carga [id=" + id + ", fecha=" + fecha + ", tipo=" + tipo + ", hojaRutaId=" + hojaRutaId + ", items="
+ items + "]";
}
}
package com.designfreed.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "CargasDet")
public class ItemCarga {
#Id
#GeneratedValue
#Column(name = "CargaDetID")
private Long id;
#Column(name = "EnvaseID")
private Integer envaseId;
#Column(name = "Lleno")
private Integer lleno;
#Column(name = "Vacio")
private Integer vacio;
#Column(name = "Averiado")
private Integer averiado;
#Column(name = "Retiro")
private Integer retiro;
#Column(name = "Entrega")
private Integer entrega;
#Column(name = "Cambio")
private Integer cambio;
public ItemCarga() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getEnvaseId() {
return envaseId;
}
public void setEnvaseId(Integer envaseId) {
this.envaseId = envaseId;
}
public Integer getLleno() {
return lleno;
}
public void setLleno(Integer lleno) {
this.lleno = lleno;
}
public Integer getVacio() {
return vacio;
}
public void setVacio(Integer vacio) {
this.vacio = vacio;
}
public Integer getAveriado() {
return averiado;
}
public void setAveriado(Integer averiado) {
this.averiado = averiado;
}
public Integer getRetiro() {
return retiro;
}
public void setRetiro(Integer retiro) {
this.retiro = retiro;
}
public Integer getEntrega() {
return entrega;
}
public void setEntrega(Integer entrega) {
this.entrega = entrega;
}
public Integer getCambio() {
return cambio;
}
public void setCambio(Integer cambio) {
this.cambio = cambio;
}
#Override
public String toString() {
return "ItemCarga [id=" + id + ", envaseId=" + envaseId + ", lleno=" + lleno + ", vacio=" + vacio
+ ", averiado=" + averiado + ", retiro=" + retiro + ", entrega=" + entrega + ", cambio=" + cambio + "]";
}
}
Thanks very much for your help
Related
I have two table Parent table is Credit in that table only one row of data is there and another one is child table Debit that contains multiple row of data. how to fetch data from two table which has to match id of parent class and child class and no duplicate is shown from parent class.
I have try with (from Credit,debit) but that can display with duplicate and not properly data is shown based on id.
package com.rojmat.entity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.springframework.core.annotation.Order;
#Entity
#Table(name="credit")
public class Credit extends BaseEntity{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private long cid;
#Column #Order
private long openingbalance;
#Column
private Date date;
#Column #Order
private long debittotal;
#Column #Order
private long drawertotal;
#Column #Order
private long debittotalplusdrawertotal;
#Column #Order
private long todaybusiness;
#OneToMany(cascade={CascadeType.ALL})
#JoinTable(name="credit_debit",
joinColumns=#JoinColumn(name="c_id"),
inverseJoinColumns=#JoinColumn(name="d_id"))
/*#JoinColumn(name="cid", referencedColumnName="cid")*/
private List<Debit> debits = new ArrayList<Debit>(Arrays.asList());
public Credit() {
}
public Credit(long cid, long openingbalance, Date date, long debittotal, long drawertotal,
long debittotalplusdrawertotal, long todaybusiness, List<Debit> debits) {
super();
this.cid = cid;
this.openingbalance = openingbalance;
this.date = date;
this.debittotal = debittotal;
this.drawertotal = drawertotal;
this.debittotalplusdrawertotal = debittotalplusdrawertotal;
this.todaybusiness = todaybusiness;
this.debits = debits;
}
public long getCid() {
return cid;
}
public void setCid(long cid) {
this.cid = cid;
}
public long getOpeningbalance() {
return openingbalance;
}
public void setOpeningbalance(long openingbalance) {
this.openingbalance = openingbalance;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public long getDebittotal() {
return debittotal;
}
public void setDebittotal(long debittotal) {
this.debittotal = debittotal;
}
public long getDrawertotal() {
return drawertotal;
}
public void setDrawertotal(long drawertotal) {
this.drawertotal = drawertotal;
}
public long getDebittotalplusdrawertotal() {
return debittotalplusdrawertotal;
}
public void setDebittotalplusdrawertotal(long debittotalplusdrawertotal) {
this.debittotalplusdrawertotal = debittotalplusdrawertotal;
}
public long getTodaybusiness() {
return todaybusiness;
}
public void setTodaybusiness(long todaybusiness) {
this.todaybusiness = todaybusiness;
}
public List<Debit> getDebit() {
return debits;
}
public void setDebit(List<Debit> debit) {
this.debits = debits;
}
/*#Override
public String toString() {
return "Credit [cid=" + cid + ", openingbalance =" + openingbalance + ", date=" + date + ", debittotal= " + debittotal + ", debittotalplusdrawertotal=" + debittotalplusdrawertotal + ", todaybusiness=" + todaybusiness + "]";
}*/
}
package com.rojmat.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="debit")
public class Debit {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private long did;
#Column
private String amount;
#Column
private String description;
public Debit() {
}
public Debit(String amount, String description) {
super();
this.amount = amount;
this.description = description;
}
public long getDid() {
return did;
}
public void setDid(long did) {
this.did = did;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return "Debit [did=" + did + ", amount =" + amount + ", description=" + description + "]";
}
}
1.CreditDaoImpl.java
package com.rojmat.daoImpl;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.rojmat.dao.CreditDao;
import com.rojmat.entity.Credit;
#Repository
public class CreditDaoImpl implements CreditDao{
#Autowired
private SessionFactory sessionFactory;
#Override
public void addCreditDebit(Credit credit) {
try {
sessionFactory.getCurrentSession().saveOrUpdate(credit);
} catch(Exception e) {
e.printStackTrace();
}
}
#Override
public void deleteCreditDebit(int cid) {
/*Credit credit = (Credit)sessionFactory.getCurrentSession().createQuery("from Credit as c LEFT JOIN FETCH c.Debit where c.cid="+cid).uniqueResult();
List<Debit> debits = credit.getDebit();
sessionFactory.getCurrentSession().delete(credit);
debits.forEach((debit) -> {
sessionFactory.getCurrentSession().delete(debit);
});*/
}
#SuppressWarnings("unchecked")
#Override
public List<Credit> getAllCreditDebit() {
List<Credit> credit = sessionFactory.getCurrentSession().createQuery("from Credit,Debit").list();
return credit;
}
}
try this example: you put "distinct" before the property you do not want to be duplicated
//SQL query
select distinct credit.idCredit as idCredit from Credit credit Left Join Debit debit on credit.idCredit= debit.idCredit
//HQL query
#Entity(name = "Credit")
#Table(name = "Credit")
public class Credit{
//if you put #Id --> HQL Query "select credit from Credit credit"
#Column(name = "idCredit")
private Long idCredit;
#Column(name = "label")
private String label;
#OneToMany
#JoinColumns({#JoinColumn(name = "idCredit" ,referencedColumnName = "idCredit")})
List<Debit> debits;
...
}
public class Debit{
....
#Column(name = "idCredit")
private Long idCredit;
...
}
Query query = getSession().createQuery("select distinct credit.idCredit as idCredit, credit.label as label, credit.debits as debits from Credit credit ");
query.setResultTransformer(Transformers.aliasToBean(Credit.class));
return query.list();
package com.rojmat.entity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.springframework.core.annotation.Order;
#Entity
#Table(name="credit")
public class Credit extends BaseEntity{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private long cid;
#Column #Order
private long openingbalance;
#Column
private Date date;
#Column #Order
private long debittotal;
#Column #Order
private long drawertotal;
#Column #Order
private long debittotalplusdrawertotal;
#Column #Order
private long todaybusiness;
#OneToMany(cascade={CascadeType.ALL})
#JoinTable(name="credit_debit",
joinColumns=#JoinColumn(name="c_id"),
inverseJoinColumns=#JoinColumn(name="d_id"))
/*#JoinColumn(name="cid", referencedColumnName="cid")*/
private List<Debit> debits = new ArrayList<Debit>(Arrays.asList());
public Credit() {
}
public Credit(long cid, long openingbalance, Date date, long debittotal, long drawertotal,
long debittotalplusdrawertotal, long todaybusiness, List<Debit> debits) {
super();
this.cid = cid;
this.openingbalance = openingbalance;
this.date = date;
this.debittotal = debittotal;
this.drawertotal = drawertotal;
this.debittotalplusdrawertotal = debittotalplusdrawertotal;
this.todaybusiness = todaybusiness;
this.debits = debits;
}
public long getCid() {
return cid;
}
public void setCid(long cid) {
this.cid = cid;
}
public long getOpeningbalance() {
return openingbalance;
}
public void setOpeningbalance(long openingbalance) {
this.openingbalance = openingbalance;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public long getDebittotal() {
return debittotal;
}
public void setDebittotal(long debittotal) {
this.debittotal = debittotal;
}
public long getDrawertotal() {
return drawertotal;
}
public void setDrawertotal(long drawertotal) {
this.drawertotal = drawertotal;
}
public long getDebittotalplusdrawertotal() {
return debittotalplusdrawertotal;
}
public void setDebittotalplusdrawertotal(long debittotalplusdrawertotal) {
this.debittotalplusdrawertotal = debittotalplusdrawertotal;
}
public long getTodaybusiness() {
return todaybusiness;
}
public void setTodaybusiness(long todaybusiness) {
this.todaybusiness = todaybusiness;
}
public List<Debit> getDebit() {
return debits;
}
public void setDebit(List<Debit> debit) {
this.debits = debits;
}
/*#Override
public String toString() {
return "Credit [cid=" + cid + ", openingbalance =" + openingbalance + ", date=" + date + ", debittotal= " + debittotal + ", debittotalplusdrawertotal=" + debittotalplusdrawertotal + ", todaybusiness=" + todaybusiness + "]";
}*/
}
package com.rojmat.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="debit")
public class Debit {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private long did;
#Column
private String amount;
#Column
private String description;
public Debit() {
}
public Debit(String amount, String description) {
super();
this.amount = amount;
this.description = description;
}
public long getDid() {
return did;
}
public void setDid(long did) {
this.did = did;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
/*#Override
public String toString() {
return "Debit [did=" + did + ", amount =" + amount + ", description=" + description + "]";
}*/
}
I am writing the criteria query to get results for jsonb in postgres.I can query the jsonb column through hibernate.I am unable to fetch jsonb specific keys.I am not able to find a way.
I have tried native query but i want some wayout in hibernate criteria query.The commonjson argument is the jsonb in postgresql is this --
{"appl_id": 726516, "applied_by": "pankajkumarnnl94#gmail.com", "service_id": 9880004, "version_no": 4, "appl_ref_no": "BSEH/2018/00728", "sub_version": 1, "payment_date": "2018-12-04T11:54:20.24+05:30", "payment_mode": "PayUbizz", "reference_no": "7726929249", "service_name": "Migration Certificate Board of School Education Haryana, Bhiwani", "department_id": 784, "location_value": 1218758, "base_service_id": 988, "department_name": " Board of School Education Haryana", "registration_id": "", "submission_date": "2018-12-04", "submission_mode": "online", "no_of_attachment": 2, "submission_location": "1578947~1218758~Board of School Education Haryana"}
Model Class ->ApplInfoJson
package com.saral.reporting.model;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Type;
import com.fasterxml.jackson.annotation.JsonProperty;
#Entity
#Table(name = "r_app_json",schema="saral1", catalog="saral1")
public class ApplInfoJson {
#Id
#Column(name = "aid")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long aid;
#Column(name = "id")
private Long id;
#JsonProperty("appl_info")
#Column(name = "appl_info")
private String applInfo;
#Column(name = "application_form_attributes")
private String applicationFormAttributes;
#Column(name = "enclosure_data")
private String enclosureData;
#Column(name = "service_id")
private Long serviceId;
#Column(name = "combined_json")
#Type(type = "JsonDataUserType")
private Map<String , Object> combinedJson;
#Column(name ="location_value")
private Long locationValue;
public Long getLocationValue() {
return locationValue;
}
public void setLocationValue(Long locationValue) {
this.locationValue = locationValue;
}
public Long getServiceId() {
return serviceId;
}
public void setServiceId(Long serviceId) {
this.serviceId = serviceId;
}
public Long getAid() {
return aid;
}
public void setAid(Long aid) {
this.aid = aid;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getApplInfo() {
return applInfo;
}
public void setApplInfo(String applInfo) {
this.applInfo = applInfo;
}
public String getApplicationFormAttributes() {
return applicationFormAttributes;
}
public void setApplicationFormAttributes(String applicationFormAttributes) {
this.applicationFormAttributes = applicationFormAttributes;
}
public String getEnclosureData() {
return enclosureData;
}
public void setEnclosureData(String enclosureData) {
this.enclosureData = enclosureData;
}
public Map<String, Object> getCombinedJson() {
return combinedJson;
}
public void setCombinedJson(Map<String, Object> combinedJson) {
this.combinedJson = combinedJson;
}
#Override
public String toString() {
return "ApplInfoJson [aid=" + aid + ", id=" + id + ", applInfo=" + applInfo + ", applicationFormAttributes="
+ applicationFormAttributes + ", enclosureData=" + enclosureData + ", serviceId=" + serviceId
+ ", combinedJson=" + combinedJson + ", locationValue=" + locationValue + "]";
}
}
Function Used->
public List<ApplInfoJson> findByCombinedJson(String commonJson) {
DetachedCriteria criteria = DetachedCriteria.forClass(ApplInfoJson.class);
List<ApplInfoJson> results = (List<ApplInfoJson>) getHibernateTemplate().findByCriteria(criteria);
return results;
}
I want some thing to pass key name and get data with specific key.
Request processing failed; nested exception is
org.springframework.orm.hibernate5.HibernateSystemException: Found
shared references to a collection:
sabeja.entity.ClassificatorObject.apartmentPayers; nested exception is
org.hibernate.HibernateException: Found shared references to a
collection: sabeja.entity.ClassificatorObject.apartmentPayers
I have been searching solution for 2 days. I found solutions in the stackoverflow, but they didn't help for me. I disabled parts of code, but I haven't caught problem.
ClassificatorObject Entity
package xm.entity;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.Table;
#Entity
#Table(name="managment_responsibilities_object")
public class ClassificatorObject implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="responsibility_id")
private int responsibilityId;
#Column(name="object_id")
private int objectId;
#Column(name="is_enabled")
private int isEnabled;
#Column(name="by_area")
private int byArea;
#Column(name="by_people")
private int byPeople;
#Column(name="by_flat")
private int byFlat;
#Column(name="is_general")
private int isGeneral;
#Column(name="sort")
private int sort;
#Column(name="not_counting")
private int notCounting;
// #OneToMany(fetch = FetchType.LAZY, mappedBy = "classificatorObject", cascade = CascadeType.ALL)
// #OrderBy("month")
// private Set<ServicePeriod> periods;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "service_id", insertable=false, updatable=false)
private Set<ServiceOption> options;
#OneToMany(fetch = FetchType.LAZY)
//#JoinColumn(name = "service_id", insertable=false, updatable=false)
#JoinColumn(
name = "object_id",
referencedColumnName = "object_id",
insertable=false, updatable=false
)
private Set<ApartmentPayer> apartmentPayers;
public Set<ApartmentPayer> getApartmentPayers() {
return apartmentPayers;
}
public void setApartmentPayers(Set<ApartmentPayer> apartmentPayers) {
this.apartmentPayers = apartmentPayers;
}
#Column(name="parent_service_id")
private int parentServiceId;
#Column(name="has_children")
private int hasChildren;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="responsibility_id", insertable=false, updatable=false)
private Classificator classificator;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="parent_service_id", insertable=false, updatable=false)
private ClassificatorObject parentService;
//CONSTRUCTORS:
public ClassificatorObject() {
}
public ClassificatorObject(int responsibilityId, int objectId, int isEnabled, int byArea, int byPeople, int byFlat,
int isGeneral, int sort, int notCounting, Set<ServicePeriod> periods, Set<ServiceOption> options,
int parentServiceId, int hasChildren, Classificator classificator) {
super();
this.responsibilityId = responsibilityId;
this.objectId = objectId;
this.isEnabled = isEnabled;
this.byArea = byArea;
this.byPeople = byPeople;
this.byFlat = byFlat;
this.isGeneral = isGeneral;
this.sort = sort;
this.notCounting = notCounting;
// this.periods = periods;
this.options = options;
this.parentServiceId = parentServiceId;
this.hasChildren = hasChildren;
this.classificator = classificator;
}
//GETTERS SETTERS:
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getResponsibilityId() {
return responsibilityId;
}
public void setResponsibilityId(int responsibilityId) {
this.responsibilityId = responsibilityId;
}
public int getObjectId() {
return objectId;
}
public void setObjectId(int objectId) {
this.objectId = objectId;
}
public int getIsEnabled() {
return isEnabled;
}
public void setIsEnabled(int isEnabled) {
this.isEnabled = isEnabled;
}
public int getByArea() {
return byArea;
}
public void setByArea(int byArea) {
this.byArea = byArea;
}
public int getByPeople() {
return byPeople;
}
public void setByPeople(int byPeople) {
this.byPeople = byPeople;
}
public int getByFlat() {
return byFlat;
}
public void setByFlat(int byFlat) {
this.byFlat = byFlat;
}
public int getIsGeneral() {
return isGeneral;
}
public void setIsGeneral(int isGeneral) {
this.isGeneral = isGeneral;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public int getNotCounting() {
return notCounting;
}
public void setNotCounting(int notCounting) {
this.notCounting = notCounting;
}
// public Set<ServicePeriod> getPeriods() {
// return periods;
// }
//
// public void setPeriods(Set<ServicePeriod> periods) {
// this.periods = periods;
// }
public Set<ServiceOption> getOptions() {
return options;
}
public void setOptions(Set<ServiceOption> options) {
this.options = options;
}
public int getParentServiceId() {
return parentServiceId;
}
public void setParentServiceId(int parentServiceId) {
this.parentServiceId = parentServiceId;
}
public int getHasChildren() {
return hasChildren;
}
public void setHasChildren(int hasChildren) {
this.hasChildren = hasChildren;
}
public Classificator getClassificator() {
return classificator;
}
public void setClassificator(Classificator classificator) {
this.classificator = classificator;
}
public ClassificatorObject getParentService() {
return parentService;
}
public void setParentService(ClassificatorObject parentService) {
this.parentService = parentService;
}
#Override
public String toString() {
return "ClassificatorObject [id=" + id + ", responsibilityId=" + responsibilityId + ", objectId=" + objectId
+ ", isEnabled=" + isEnabled + ", byArea=" + byArea + ", byPeople=" + byPeople + ", byFlat=" + byFlat
+ ", isGeneral=" + isGeneral + ", sort=" + sort + ", notCounting=" + notCounting + ", parentServiceId="
+ parentServiceId + ", hasChildren=" + hasChildren + "]";
}
}
ApartmentPayer Entity
package sabeja.entity;
import java.math.BigDecimal;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name="sb_flat_payers")
public class ApartmentPayer {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private Integer id;
#Column(name="flat_id")
private int flatId;
#Column(name="payer_id")
private int payerId;
#Column(name="object_id")
private int objectId;
#Column(name="area", columnDefinition="Decimal(12,2)")
private BigDecimal area;
#Column(name="people_number")
private int peopleNumber;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name="flatPayer_id", insertable=false, updatable=false)
private Set<ServiceOption> options;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="payer_id", insertable= false, updatable= false)
private User user;
// #ManyToOne(fetch = FetchType.LAZY)
// #JoinColumn(name="object_id", insertable=false, updatable=false)
// private TheObject theObject;
public ApartmentPayer() {
super();
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Set<ServiceOption> getOptions() {
return options;
}
public void setOptions(Set<ServiceOption> options) {
this.options = options;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public int getFlatId() {
return flatId;
}
public void setFlatId(int flatId) {
this.flatId = flatId;
}
public int getPayerId() {
return payerId;
}
public void setPayerId(int payerId) {
this.payerId = payerId;
}
public BigDecimal getArea() {
return area;
}
public void setArea(BigDecimal area) {
this.area = area;
}
public int getPeopleNumber() {
return peopleNumber;
}
public void setPeopleNumber(int peopleNumber) {
this.peopleNumber = peopleNumber;
}
public int getObjectId() {
return objectId;
}
public void setObjectId(int objectId) {
this.objectId = objectId;
}
// public TheObject getTheObject() {
// return theObject;
// }
//
//
//
// public void setTheObject(TheObject theObject) {
// this.theObject = theObject;
// }
#Override
public String toString() {
return "ApartmentPayer [id=" + id + ", flatId=" + flatId + ", payerId=" + payerId + ", area=" + area
+ ", peopleNumber=" + peopleNumber + "]";
}
}
DAOIMPL
Query<Apartment> queryResult2 = currentSession
.createQuery("SELECT DISTINCT a FROM Apartment a "
+ "JOIN FETCH a.theObject o "
+ "JOIN FETCH o.services s "
+ "JOIN FETCH s.apartmentPayers ap "
// + "LEFT JOIN FETCH s.options op "
// + "JOIN ServicePeriod p ON s.id = p.responsibilities_object_id "
// + "JOIN FETCH ap.user u "
+ "WHERE a.houseId = :object_id "
// + "AND (op.flatPayerId = ap.id OR op.id is NULL) "
//+ "AND (SELECT count(*) FROM DisabledPayer di WHERE di.serviceId = s.id AND di.flatPayerId = ap.id) = 0"
// + "AND (CASE WHEN op.is_disabled = 0 THEN 1 WHEN op.is_disabled = 1 "
// + "THEN 0 END) = 1) OR op.id IS NULL"
, Apartment.class);
This error can happen in some specific cases when you have kind of a 'loop' reference, but in this case you don't have a class with a field that uses this same class.
So the error has to be in a call to the method setApartmentPayers(), you need to check all the calls to the method and ensure that you are not assigning the same collection to two different entities.
I have this two clases:
package cu.jpa.entities.views;
import cu.jpa.entities.BaseEntity;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import java.util.List;
#Entity
#NamedQuery(
name="SubstanceDescriptionEntity.findAll",
query="select " +
" new cu.jpa.entities.views.SubstanceDescriptionEntity(S.id, S.substanceId) " +
"from " +
" SubstanceEntity S "
)
public class SubstanceDescriptionEntity extends BaseEntity {
private int id;
private String substanceId;
private List<PatternDescriptionEntity> patterns;
public SubstanceDescriptionEntity(int id, String substanceId){
this.id = id;
this.substanceId = substanceId;
}
public SubstanceDescriptionEntity(){
}
#Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSubstanceId() {
return substanceId;
}
public void setSubstanceId(String substanceId) {
this.substanceId = substanceId;
}
#OneToMany(mappedBy = "substance")
public List<PatternDescriptionEntity> getPatterns() {
return patterns;
}
public void setPatterns(List<PatternDescriptionEntity> patterns) {
this.patterns = patterns;
}
}
This is class 2:
package cu.jpa.entities.views;
import cu.jpa.entities.BaseEntity;
import javax.persistence.*;
#Entity
#NamedQuery(
name="PatternDescriptionEntity.findAll",
query="select " +
" new cu.jpa.entities.views.PatternDescriptionEntity(P.id, " +
" E.encounterId, " +
" P.patternId, " +
" E.substanceId) " +
"from " +
" PatternEntity P " +
" inner join " +
" P.encounterByEncounterId E " +
" where P.encounterId = E.id "
)
public class PatternDescriptionEntity extends BaseEntity {
private int id;
private String patternId;
private String encounterId;
private int substanceId;
private SubstanceDescriptionEntity substance;
public PatternDescriptionEntity(int id, String encounterId, String patternId, int substanceId){
this.id = id;
this.patternId = patternId;
this.encounterId = encounterId;
this.substanceId = substanceId;
}
public PatternDescriptionEntity(){
}
#Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPatternId() {
return patternId;
}
public void setPatternId(String patternId) {
this.patternId = patternId;
}
public String getEncounterId() {
return encounterId;
}
public void setEncounterId(String encounterId) {
this.encounterId = encounterId;
}
public int getSubstanceId() {
return substanceId;
}
public void setSubstanceId(int substanceId) {
this.substanceId = substanceId;
}
#ManyToOne
#JoinColumn(name = "substanceId", insertable = false, updatable = false, referencedColumnName = "substanceId")
public SubstanceDescriptionEntity getSubstance() {
return substance;
}
public void setSubstance(SubstanceDescriptionEntity substance) {
this.substance = substance;
}
}
Both classes are the result of a named query execution. I can get all the elements correctly using this:
#Override
public List<PatternDescriptionEntity> findAll(){
Query query = entityManager.createNamedQuery("PatternDescriptionEntity.findAll",PatternDescriptionEntity.class);
List<PatternDescriptionEntity> items = query.getResultList();
return items;
}
The problem is that I would like to get the reference to the SubstanceDescriptionEntity that corresponds to the PatternDescriptionEntity, according to the details I think I should have placed in #ManyToOne annotation. Both entities are the result of a named query, not of a table mapping. That is why I am having troubles. Because when I execute this test:
#Autowired
PatternDescriptionService service;
#Test
public void test_count_with_filters() throws Exception {
List<PatternDescriptionEntity> patterns = service.findAll();
}
I can see the patterns list with values, but each individual instance of the list has the property substance in null, which means the mapping have some sort of trouble, which I can quite figure it out.
So the question is:
I have these two JPA Entities (not mapped to database tables, but to to named queries result). How can I define the relations of ManyToOne and OneToMany?
In Hibernate 4, inner join is used for child objects while accessing objects of "one table per subclass".
[Edit: This is a bug in Hibernate 4.3.5, and it is going to be fixed in 4.3.6. https://hibernate.atlassian.net/browse/HHH-8980 ]
I have the following classes.
Professor - Base Class
ContractProfessor - Derived Class from Professor
FulltimeProfessor - Derived Class from Professor
FulltimeProfessor contains a mandatory object of Department. [Not null at SQL]
Classroom contains an object of Professor, which can be null.
When I query Classroom, I am getting errors. When I saw the query, it is doing inner join with Department. If the classroom that it is retrieving is of ContractProfessor, then it won't have Department, and the inner join fails, and it is throwing exception.
Since, the Professor object can be null, it should always use left join for all the joins. But, it is doing inner join between FulltimeProfessor and Department. Because of that, I am getting exceptions when I try to retrieve Classroom objects.
This is working fine in Hibernate 3. But, when I use hibernate 4.3.5-Final, I am getting errors.
What should I do to fix this without changing the DB schema?
The following is the code and sql for the same.
Generated Query in Hibernate 4.3.5-Final
select
professor0_.id as id1_6_0_,
professor0_.name as name2_6_0_,
professor0_1_.hourlyRate as hourlyRa1_2_0_,
professor0_2_.DepartmentId as Departme3_4_0_,
professor0_2_.salary as salary1_4_0_,
case
when professor0_1_.id is not null then 1
when professor0_2_.id is not null then 2
when professor0_.id is not null then 0
end as clazz_0_,
department1_.id as id1_3_1_,
department1_.name as name2_3_1_
from
Professor professor0_
left outer join
ContractProfessor professor0_1_
on professor0_.id=professor0_1_.id
left outer join
FulltimeProfessor professor0_2_
on professor0_.id=professor0_2_.id
inner join
Department department1_
on professor0_2_.DepartmentId=department1_.id
where
professor0_.id=?
Generated Query in Hibernate 3.
select
professor0_.id as id2_1_,
professor0_.name as name2_1_,
professor0_1_.hourlyRate as hourlyRate3_1_,
professor0_2_.DepartmentId as Departme3_8_1_,
professor0_2_.salary as salary8_1_,
case
when professor0_1_.id is not null then 1
when professor0_2_.id is not null then 2
when professor0_.id is not null then 0
end as clazz_1_,
department1_.id as id1_0_,
department1_.name as name1_0_
from
Professor professor0_
left outer join
ContractProfessor professor0_1_
on professor0_.id=professor0_1_.id
left outer join
FulltimeProfessor professor0_2_
on professor0_.id=professor0_2_.id
left outer join
Department department1_
on professor0_2_.DepartmentId=department1_.id
where
professor0_.id=?
Professor.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
#Entity
#Table(name = "Professor")
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Professor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
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 toString() {
return "Professor id: " + getId() + " name: " + getName();
}
}
ContractProfessor.java
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name="ContractProfessor")
public class ContractProfessor extends Professor {
private long hourlyRate = 1;
public long getHourlyRate() {
return hourlyRate;
}
public void setHourlyRate(long hourlyRate) {
this.hourlyRate = hourlyRate;
}
public String toString() {
return "ContractProfessor id: " + getId() + " name: " + getName();
}
}
FulltimeProfessor.java
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
#Entity
#Table(name="FulltimeProfessor")
public class FulltimeProfessor extends Professor {
private long salary = 1;
#ManyToOne(fetch = FetchType.EAGER)
#Fetch(FetchMode.JOIN)
#JoinColumn(name = "DepartmentId", nullable = false)
private Department department;
public Department getDepartment()
{
return department;
}
public void setDepartment(Department department)
{
this.department = department;
}
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
public String toString() {
return "FullTimeProfessor id: " + getId() + " name: " + getName();
}
}
Department.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "Department")
public class Department
{
private long id;
private String name;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
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 toString() {
return "Department id: " + getId() + " name: " + getName();
}
}
Classroom.java
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
#Entity
#Table(name = "Classroom")
public class Classroom
{
private long id;
private String name;
private Professor professor;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
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 toString() {
return "Classroom id: " + getId() + " name: " + getName();
}
#ManyToOne(fetch = FetchType.EAGER)
#Fetch(FetchMode.JOIN)
#JoinColumn(name = "ProfessorId", nullable = true)
public Professor getProfessor()
{
return professor;
}
public void setProfessor(Professor professor)
{
this.professor = professor;
}
}
InnerJoinMain.java
import java.util.Collection;
import java.util.Date;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class InnerJoinMain
{
public static void main(String[] args) throws Exception
{
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ProfessorService");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
int time = (int)((new Date().getTime() / 1000) % 10000);
System.out.println(time);
ContractProfessor cprof = new ContractProfessor();
cprof.setName("CProf" + time);
cprof.setHourlyRate(time);
em.persist(cprof);
Department dept = new Department();
dept.setName("Dept" + time);
em.persist(dept);
FulltimeProfessor fprof = new FulltimeProfessor();
fprof.setName("Fprof" + time);
fprof.setDepartment(dept);
fprof.setSalary(time + 10);
em.persist(fprof);
Classroom cls = new Classroom();
cls.setName("Classroom" + time);
cls.setProfessor(cprof);
em.persist(cls);
cls = new Classroom();
cls.setName("Classroom" + (time+1));
cls.setProfessor(fprof);
em.persist(cls);
cls = new Classroom();
cls.setName("Classroom" + (time+2));
em.persist(cls);
em.getTransaction().commit();
em.getTransaction().begin();
Query query = em.createQuery("SELECT c FROM Classroom c");
for(Classroom c : (Collection<Classroom>) query.getResultList()) {
System.out.println(c);
}
em.getTransaction().commit();
em.close();
emf.close();
}
}