Sorting by connected column from another entity - java

I have two entities:
public class Garden implements Serializable {
private static final long serialVersionUID = -1198096323173371453L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private Integer number;
#Column(name = "plot_number", nullable = false)
private Integer plotNumber;
#Column(name = "person_id", insertable = false, updatable = false)
private int personId;
#ManyToOne
private Person person;
}
#Table(name = "person")
public class Person implements Serializable {
private static final long serialVersionUID = -6257724189464155057L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence")
#SequenceGenerator(name = "person_sequence", sequenceName = "person_id_seq", allocationSize = 1)
#Column(unique = true, nullable = false)
private Integer id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
}
I am trying make sort on backend by columns. For sorting I use
final SpecificationUtil gardenSpecification = new SpecificationUtil<>();
final List<Specification<Garden>> searchSpecification = gardenSpecification.createSearchSpecificationRaw(request);
final Specification<Garden> specificationResult = searchSpecification.stream().reduce(null, Specification::and);
Sort.Direction direction = Sort.Direction.ASC;
if (request.getOrderDirection().equals("desc")) {
direction = Sort.Direction.DESC;
}
return gardenDataService.findAll(specificationResult, Sort.by(direction, request.getOrderColumn()));
public List<Specification<T>> createSearchSpecificationRaw(DataGridRequest request) {
final List<Specification<T>> specifications = new ArrayList<>();
if (request.getSearchColumns() != null && !request.getSearchColumns().isEmpty()) {
for (ColumnSearch search : request.getSearchColumns()) {
if (StringUtils.isEmpty(search.getSearchValue())) {
continue;
}
specifications.add(create(search.getColumnName(), search.getSearchValue()));
}
}
return specifications;
}
/**
* create specification
*
* #param columnKey
* #param value
* #return
*/
private Specification<T> create(String columnKey, String value) {
final GenericSpecificationFactory<T> specificationFactory = new GenericSpecificationFactory<>();
return specificationFactory.createLike(columnKey, value);
}
when I sort by column in Garden, sorting is OK. But when I want sort by lastName I get error:
org.springframework.data.mapping.PropertyReferenceException: No property lastName found for type Garden!
Can you help me how the best make sorting on connected column from another entity.
Thank you.

Related

Duplicate parent and child data in jpql (JPA)

I have a Production class and ProductionDetail entity class where Id of Production table is a foreignKey as production_id in ProductionDetail entity class so my both entity class with mapping has given bellow
Production Entity Class:
#Entity
#Table(name = "tbl_production")
#XmlRootElement
public class TblProduction implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "ID")
private String id;
#Column(name = "PRODUCTION_DATE")
#Temporal(TemporalType.DATE)
private Date productionDate;
#Column(name = "START_DATETIME")
#Temporal(TemporalType.TIMESTAMP)
private Date startDatetime;
#Column(name = "END_DATETIME")
#Temporal(TemporalType.TIMESTAMP)
private Date endDatetime;
#Size(max = 45)
#Column(name = "MACHINE_UUID")
private String machineUuid;
**Relation with Production Details Table**
#OneToMany(mappedBy = "production")
#XmlElement(name = "productionDetails")
private List<TblProductionDetail> productionDetailList;
#PrimaryKeyJoinColumn(name = "MACHINE_UUID", referencedColumnName = "UUID")
#ManyToOne(fetch = FetchType.LAZY)
private MstMachine mstMachine;
#XmlTransient
public MstMachine getMstMachine() {
return this.mstMachine;
}
}
Production Details Entity Class:
#Entity
#Table(name = "tbl_production_detail")
#XmlRootElement
public class TblProductionDetail implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "ID")
private String id;
#Size(max = 45)
#Column(name = "COMPONENT_ID")
private String componentId;
#Size(max = 45)
#Column(name = "PRODUCTION_ID")
private String productionId;
**Relation with Production Class**
#ManyToOne
#JoinColumn(name = "PRODUCTION_ID", referencedColumnName = "ID", insertable = false,
updatable = false)
private TblProduction production;
#Transient
public String componentCode;
#Transient
public String componentName;
#PrimaryKeyJoinColumn(name = "COMPONENT_ID", referencedColumnName = "ID")
#ManyToOne(fetch = FetchType.LAZY)
private MstComponent mstComponent;
#XmlTransient
public MstComponent getMstComponent() {
return this.mstComponent;
}
public void setMstComponent(MstComponent mstComponent) {
this.mstComponent = mstComponent;
}
}
ParentList Class:
public class TblProductionList {
private List<TblProduction> productionList;
public TblProductionList() {
productionList = new ArrayList<>();
}
public List<TblProduction> getTblProductions() {
return productionList;
}
public void setTblProductions(List<TblProduction> tblProductionList) {
this.productionList = tblProductionList;
}
}
BusinessLogic(DAO Class):
public TblProductionList getJson() {
TblProductionList response = new TblProductionList();
StringBuilder retrieveQuery = new StringBuilder();
retrieveQuery.append(" SELECT prod FROM TblProduction prod ");
retrieveQuery.append(" JOIN FETCH prod.productionDetailList ");
retrieveQuery.append(" WHERE prod.endDatetime IS NULL ");
retrieveQuery.append(" AND prod.machineUuid IS NOT NULL ");
retrieveQuery.append(" AND NOT EXISTS (SELECT tpt FROM
TblProductionThset tpt WHERE prod.id = tpt.productionId) ");
retrieveQuery.append(" AND EXISTS (SELECT mmfd FROM
MstMachineFileDef mmfd WHERE prod.machineUuid = mmfd.machineUuid
AND mmfd.hasThreshold = 1) ");
retrieveQuery.append(" ORDER BY prod.id ");
Query query =
entityManager.createQuery(retrieveQuery.toString());
List thresholdList = query.getResultList();
response.setTblProductions(thresholdList);
return response;
}
According to the database I am getting expected master child data like below
After designing this entity class I am expecting that I will get 3 master records where each record has 2 detail records. But I am getting 6 duplicate master records with 12 child records. Can anyone suggest to me please where is my code became wrong and why this situation raised? please check the JSON data that I am getting from API.
change your array list to hash set then records are not duplicate.

Using JPA Criteria API to return all object where a Collection property contains a certain value

I am trying to dynamicaly create a Specification for my Spring-data-jpa project
Here is my specification for the moment:
public class DemandsSpecs implements Specification<SvDem> {
private static final Logger LOG = LogManager.getLogger();
private final DemandsCritera critera;
private final List<Predicate> predicateList;
public DemandsSpecs(final DemandsCritera critera) {
this.critera = critera;
this.predicateList = new ArrayList<>();
}
#Override
public Predicate toPredicate(final Root<SvDem> root,
final CriteriaQuery<?> query,
final CriteriaBuilder cb) {
this.predicateList.add(cb.between(root.get(SvDem_.hdCreation), critera.getBegin(), critera.getEnd()));
if (critera.getSoc() != null) {
LOG.debug("socId {}", critera.getSoc());
this.predicateList.add(cb.equal(root.get(SvDem_.socId), critera.getSoc()));
}
if (critera.getManagementAct() != null) {
LOG.debug("actgesId {}", critera.getManagementAct());
this.predicateList.add(cb.equal(root.get(SvDem_.actgesId), critera.getManagementAct()));
}
if (critera.getStatus() != null) {
LOG.debug("statutId {}", critera.getStatus());
this.predicateList.add(cb.equal(root.get(SvDem_.statutId), critera.getStatus()));
}
if (!StringUtils.isBlank(critera.getId())) {
LOG.debug("id {}", critera.getId());
this.predicateList.add(cb.like(root.get(SvDem_.id), '%' + critera.getId() + '%'));
}
return query.where(cb.and(predicateList.toArray(new Predicate[predicateList.size()])))
.orderBy(cb.desc(root.get("hdCreation")))
.getRestriction();
}
}
The DemandsCritera also have a String property metadata.
public class DemandsCritera implements Serializable {
private static final Long serialVersionUID = 1L;
private Date begin;
private Date end;
private RfActges managementAct;
private String metadata;
private RfStatut status;
private RfSoc soc;
private String id;
/* getters and setters */
}
SvDem has a property svMetaCollection which is a Collection<SvMeta>.
#Entity
#Table(name = "sv_dem")
public class SvDem implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
private String id;
#Basic(optional = false)
#Column(name = "HD_CREATION")
#Temporal(TemporalType.TIMESTAMP)
private Date hdCreation;
#Lob
private String user;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "svDem")
#JsonManagedReference
private Collection<SvMeta> svMetaCollection;
#JoinColumn(name = "ACTGES_ID", referencedColumnName = "ID")
#ManyToOne(optional = false)
private RfActges actgesId;
#JoinColumn(name = "STATUT_ID", referencedColumnName = "ID")
#ManyToOne(optional = false)
private RfStatut statutId;
#JoinColumn(name = "SOC_ID", referencedColumnName = "ID")
#ManyToOne(optional = false)
private RfSoc socId;
/* getters, setters and other irrelevant properties */
}
The SvMeta object has a String property value
#Entity
#Table(name = "sv_meta")
public class SvMeta implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected SvMetaPK svMetaPK;
#Basic(optional = false)
#Lob
private String value;
#JoinColumn(name = "META_ID", referencedColumnName = "ID", insertable = false, updatable = false)
#ManyToOne(optional = false)
private RfMeta rfMeta;
#JoinColumn(name = "DEM_ID", referencedColumnName = "ID", insertable = false, updatable = false)
#ManyToOne(optional = false)
#JsonBackReference
private SvDem svDem;
}
I want to return all the SvDem where any of its SvMeta has a value equals to the DemandsCritera.metadata.
How can I achieve that?
I just needed to add this to my toPredicate method of DemandsSpecs:
if (!StringUtils.isBlank(critera.getMetadata())) {
LOG.debug("metadata {}", critera.getMetadata());
Join<SvDem, SvMeta> metas = root.join(SvDem_.svMetaCollection);
this.predicateList.add(cb.equal(metas.get(SvMeta_.value), critera.getMetadata()));
}

Using JPA NamedQuery to obtain result list

I want to get a list of results using the query as below:
SELECT x FROM XTreinamentosOrc x WHERE x.codEduca NOT IN (SELECT DISTINCT y.codCurso y FROM XRlz y WHERE y.matricula = :matricula)
I have used it in its entity class, but then I've got the Exception:
Caused by: javax.el.PropertyNotFoundException: The class 'br.com.bb.upb.diage.atb_treinamentos.entities.XTreinamentosOrc' does not have the property 'matricula'.
The matricula field is obtained when the user successfully logs in the app.
It should be setted in the NamedQuery via CDI to query the database.
The matricula field is located in another table different from the one mapped here.
How can I set the injected sessionChave String in parameter matricula, which is of XRlzConsolidado class type?
The bean:
#Named(value = "ExtratoBean")
#RequestScoped
public class ExtratoBean implements Serializable {
#EJB
private XTreinamentosOrcFacade xt;
#Inject
#SessionChave
private String sessionChave;
private List<XTreinamentosOrc> xTreinamentosOrcList;
public List<XTreinamentosOrc> getxTreinamentosOrcList() {
return QueryExtratoTreinamentos();
}
private List QueryExtratoTreinamentos() {
List<XTreinamentosOrc> extratoTreinamentosOrcList = null;
XRlzConsolidado x = new XRlzConsolidado();
x.setMatricula(sessionChave);
extratoTreinamentosOrcList = xt.findAllTreinamentosByMatricula(x);
return extratoTreinamentosOrcList;
}
}
There are 3 entities: XRlz, XRlzConsolidado and XTreinamentosOrc.
The XRlz:
#Entity
#Table(name = "XRlz", catalog = "diage", schema = "atb")
#XmlRootElement
//named queries
public class XRlz implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Size(max = 100)
#Column(name = "nome")
private String nome;
#Column(name = "uorPos")
private Integer uorPos;
#Size(max = 100)
#Column(name = "nomeUorPos")
private String nomeUorPos;
#Column(name = "codCurso")
private Integer codCurso;
#Size(max = 100)
#Column(name = "nomeCurso")
private String nomeCurso;
#Column(name = "qtdCursos2015")
private Integer qtdCursos2015;
#Size(max = 10)
#Column(name = "dtConclusao")
private String dtConclusao;
#JoinColumn(name = "matricula", referencedColumnName = "matricula")
#ManyToOne
private XRlzConsolidado matricula;
#JoinColumn(name = "dtRef", referencedColumnName = "id")
#ManyToOne
private XDatas dtRef;
//GETTERS AND SETTERS
public XRlzConsolidado getMatricula() {
return matricula;
}
public void setMatricula(XRlzConsolidado matricula) {
this.matricula = matricula;
}
public XDatas getDtRef() {
return dtRef;
}
public void setDtRef(XDatas dtRef) {
this.dtRef = dtRef;
}
//equals/hashcode/toString
}
The XRlzConsolidado:
#Entity
#Table(name = "XRlzConsolidado", catalog = "diage", schema = "atb")
#XmlRootElement
// NamedQueries
public class XRlzConsolidado implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 8)
#Column(name = "matricula")
private String matricula;
#Size(max = 100)
#Column(name = "nome")
private String nome;
#Column(name = "uorPos")
private Integer uorPos;
#Size(max = 100)
#Column(name = "nomeuorPos")
private String nomeuorPos;
#Column(name = "capacitacaoGestores")
private Integer capacitacaoGestores;
#Column(name = "capacitacaoAssessores")
private Integer capacitacaoAssessores;
#Column(name = "horas")
private Integer horas;
#Column(name = "bemEstar")
private Integer bemEstar;
#Column(name = "inovEfic")
private Integer inovEfic;
#Column(name = "qtdCursos2015")
private Integer qtdCursos2015;
#OneToMany(mappedBy = "matricula")
private Collection<XRlz> xRlzCollection;
public XRlzConsolidado() {
}
public XRlzConsolidado(String matricula) {
this.matricula = matricula;
}
public String getMatricula() {
return matricula;
}
public void setMatricula(String matricula) {
this.matricula = matricula;
}
// getters and setters
#XmlTransient
public Collection<XRlz> getXRlzCollection() {
return xRlzCollection;
}
public void setXRlzCollection(Collection<XRlz> xRlzCollection) {
this.xRlzCollection = xRlzCollection;
}
// hashCode()
#Override
public boolean equals(Object object) {
if (!(object instanceof XRlzConsolidado)) {
return false;
}
XRlzConsolidado other = (XRlzConsolidado) object;
if ((this.matricula == null && other.matricula != null) || (this.matricula != null && !this.matricula.equals(other.matricula))) {
return false;
}
return true;
}
// toString
}
The XTreinamentosOrc:
#Entity
#Table(name = "XTreinamentosOrc", catalog = "diage", schema = "atb")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "XTreinamentosOrc.findAll", query = "SELECT x FROM XTreinamentosOrc x"),
#NamedQuery(name = "XTreinamentosOrc.findAllTreinamentosByMatricula", query = "SELECT x FROM XTreinamentosOrc x WHERE x.codEduca NOT IN (SELECT DISTINCT y.codCurso FROM XRlz y WHERE y.matricula = :matricula)")})
public class XTreinamentosOrc implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Column(name = "codEduca")
private int codEduca;
#Size(max = 100)
#Column(name = "nomeCurso")
private String nomeCurso;
#Column(name = "cargaHoraria")
private Integer cargaHoraria;
#JoinColumn(name = "tipo", referencedColumnName = "id")
#ManyToOne(optional = false)
private XTipo tipo;
#JoinColumn(name = "segmento", referencedColumnName = "id")
#ManyToOne(optional = false)
private XSegmento segmento;
#JoinColumn(name = "modalidade", referencedColumnName = "id")
#ManyToOne
private XModalidade modalidade;
#JoinColumn(name = "dtRef", referencedColumnName = "id")
#ManyToOne
private XDatas dtRef;
public XTreinamentosOrc() {
}
public XTreinamentosOrc(Integer id) {
this.id = id;
}
public XTreinamentosOrc(Integer id, int codEduca) {
this.id = id;
this.codEduca = codEduca;
}
// hashCode() {
#Override
public boolean equals(Object object) {
if (!(object instanceof XTreinamentosOrc)) {
return false;
}
XTreinamentosOrc other = (XTreinamentosOrc) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
}
Thanks in advance.
I believe the problem lies in the name of your query. findAllTreinamentosByMatricula() is a Property Expression and can refer only to a direct property of the managed entity. findAllTreinamentosByMatricula will look in the XTreinamentosOrc class for the property called matricula. When that property is not found in XTreinamentosOrc you get the exception:
Caused by: javax.el.PropertyNotFoundException: The class 'br.com.bb.upb.diage.atb_treinamentos.entities.XTreinamentosOrc' does not have the property 'matricula'.
You need to change the name of your query to something like:
#NamedQuery(name = "XTreinamentosOrc.find", query = "SELECT x FROM XTreinamentosOrc x WHERE x.codEduca NOT IN (SELECT DISTINCT y.codCurso FROM XRlz y WHERE y.matricula = :matricula)")})
(I may be off with the method name 'find() so you may need to do some more research' for acceptable format)
check out this documentation:
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
Could you post code for XRlzConsolidado? It probably contains a string field you want to compare with sessionChave. You are comparing field XRlz.matricula with string value, but it is of type XRlzConsolidado

Saving entity using crudrepository taking too much time

I am trying to update an entry in the DB using crudrepository but its taking ~ 24 seconds for each iteration. Below is the code. Thanks in advance.
for(tmp.request.Number numb : Num_list){
EnterpriseVnumbList addNumb = entNumbdao.findByVnumbmsisdnAndEnterpriseid(numb.getNumber(), frmEntp);
if(addNumb != null){
addNumb.setEnterpriseId(toEntp); // toEnt is a class Enterprise
entNumbdao.save(addNumb); // entNumbdao is EnterpriseVnumbListRepo
addEntpToEnt++;
}else{
log.error("NumbProcessing: Failed to");
}
Here is my EnterpriseVnumbList class
#Entity
#Table(name = "enterprise_vnumb_list", uniqueConstraints = {
#UniqueConstraint(columnNames = {"vnumb_msisdn"})})
#XmlRootElement
public class EnterpriseVnumbList implements Serializable {
#Size(max = 10)
#Column(name = "parent_id")
private String parentId;
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id", nullable = false)
private Long id;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 30)
#Column(name = "vnumb_msisdn", nullable = false, length = 30)
private String vnumbmsisdn;
#Size(max = 30)
#Column(name = "imsi", length = 30)
private String imsi;
#Column(name = "assigned")
private Boolean assigned;
#Size(max = 30)
#Column(name = "assigned_to_sim", length = 30)
private String assignedtosim;
#JoinColumn(name = "enterprise_id", referencedColumnName = "enterprise_id", nullable = false)
#ManyToOne(optional = false)
private Enterprise enterpriseid;
/// Some code here
}
// Here is EnterpriseVnumbListRepo class
#RepositoryDefinition(domainClass=EnterpriseVnumbList.class, idClass=Integer.class)
public interface EnterpriseVnumbListRepo extends CrudRepository<EnterpriseVnumbList, Integer>, JpaSpecificationExecutor<EnterpriseVnumbList>{
EnterpriseVnumbList findByVnumbmsisdnAndEnterpriseidAndAssigned(String vsim, Enterprise enterpriseid, boolean assgn);
EnterpriseVnumbList findByVnumbmsisdnAndEnterpriseid(String vsim, Enterprise enterpriseid);
List<EnterpriseVnumbList> findByEnterpriseidAndAssigned(Enterprise entp, boolean assgn);
EnterpriseVnumbList findByVnumbmsisdnAndAssignedtosim(String vsim, String sim);
EnterpriseVnumbList findByVnumbmsisdnAndEnterpriseidAndAssignedNot(String vsim, Enterprise enterpriseid, boolean assgn);
Long countByEnterpriseidAndAssigned(Enterprise entp, boolean assgn);
Long countByEnterpriseid(Enterprise entp);
}

JPA - Issues removing child entities on bidirectional mapping

I need to remove a child entity called "SystemParamater" based on the it´s id.
What i was trying to do:
- Begin Tran
SystemParameter param EntityManager.find(SystemParameter.class,<paremeter.id>)
EntityManager.remove(param)
-Commit tran
But the entity was not removed.
What´s the correct way to remove a child entity?
Below, you could find my entities:
SystemParameter:
#Entity
#Table(name = "system_parameters")
#Cacheab le
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SystemParameter extends BasicEntity {
private static final long serialVersionUID = -6416605270912358340L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "paramName", length = 50, nullable = false)
private String paramName;
#Column(name = "paramValue", length = 255, nullable = false)
private String paramValue;
#Column(name = "encrypted", nullable = false)
#Type(type = "yes_no")
private Boolean encrypted = Boolean.FALSE;
#ManyToOne
#JoinColumn(name = "groupId", nullable = false)
private SystemParameterGroup parameterGroup;
}
SystemParameterGroup:
#Entity
#Table(name = "system_parameter_groups", uniqueConstraints = { #UniqueConstraint(columnNames = { "searchKey" }) })
#Cacheable
public class SystemParameterGroup extends BasicEntity {
private static final long serialVersionUID = -1762633144642103487L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name", length = 50, nullable = false)
private String name;
/**
* Description.
*/
#Column(name = "description", length = 255, nullable = false)
private String description;
/**
* Search key.
*/
#Column(name = "searchKey", length = 50, nullable = false)
private String searchKey;
/**
* System parameter list.
*/
#OneToMany(fetch = FetchType.EAGER, mappedBy = "parameterGroup", cascade = CascadeType.ALL, orphanRemoval = true)
#OrderBy("paramName")
private List<SystemParameter> systemParameterList;
}
You have to remove the SystemParameter entity also from the SystemParameterGroup's list of SystemParameter:
systemParameterGroup.getSystemParameterList().remove(systemParameter);
This issue is related to this one.

Categories

Resources