I'm trying to query a mongo repository to return data that is within a specified geo circle. I'm using the following code:
Page<Img> findByLocationWithin(Circle circle, Pageable pageable);
and then in my controller I'm using:
Distance distance = new Distance(7.5, Metrics.MILES);
Circle circle = new Circle(location, distance);
Page<Img> results = imgRepository.findByLocationWithin(circle, pageable);
However it definitely doesn't use a radius of 7.5 miles as if I create the circle a few hundred metres away from where the data is located, it returns nothing. I've checked the logs in mongo and it says that the following code is being performed:
"location" : {
"$within" : {
"$center" : [
[
30.198,
-1.695
],
0.0018924144710663706
]
}
}
This means it's not using $geoWithin or $centerSphere. How can I fix these problems?
I had the same problem with spring and Couchbase... but the query is not the problem... Because Spring convert the distance in the geometric values.
In my case I also returned null, but my problem was solved, in the model class, the attribute that specifies the coordinate [x, y] must be of type Library Point org.springframework.data.geo.Point;
package com.webServices.rutas.model;
import org.springframework.data.couchbase.core.mapping.id.GeneratedValue;
import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy;
import org.springframework.data.geo.Point;
import com.couchbase.client.java.repository.annotation.Field;
import com.couchbase.client.java.repository.annotation.Id;
public class Parada {
#Id #GeneratedValue(strategy = GenerationStrategy.UNIQUE)
private String id;
#Field
private String type;
#Field
private String nombre;
#Field
private String urlFoto;
#Field
private Point coordenada;
public Parada(String nombre, String urlFoto, Point coordenada) {
super();
this.type = "parada";
this.nombre = nombre;
this.urlFoto = urlFoto;
this.coordenada = coordenada;
}
public Parada() {
super();
this.type = "parada";
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getUrlFoto() {
return urlFoto;
}
public void setUrlFoto(String urlFoto) {
this.urlFoto = urlFoto;
}
public Point getCoordenada() {
return coordenada;
}
public void setCoordenada(Point coordenada) {
this.coordenada = coordenada;
}
#Override
public String toString() {
return "Parada [id=" + id + ", type=" + type + ", nombre=" + nombre + ", urlFoto=" + urlFoto + ", coordenada="
+ coordenada + "]";
}
}
In the service:
public Iterable<Parada> getParadasCercanasRadio(Punto punto){
Point cuadro = new Point(-2.2,-80.9);
Circle circle = new Circle(cuadro,new Distance(300000, Metrics.KILOMETERS));
return paradaRepository.findByCoordenadaWithin(circle);
}
In the Repository:
#Dimensional(designDocument = "paradas", spatialViewName = "paradas")
Iterable<Parada> findByCoordenadaWithin(Circle p);
P.D. Sorry for my English.
Related
Can anyone please help me on how to send a nested json requestbody in postman for the below entity class.
ProcessRequestInfo.java
import java.sql.Date;
import java.time.ZonedDateTime;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="PROCESS_REQUEST_INFO")
public class ProcessRequestInfo {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
private String userName;
private String contactNumber;
#Embedded
private DefectiveComponentInfo defectiveComponentInfo;
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 getContactNumber() {
return contactNumber;
}
public void setContactNumber(String contactNumber) {
this.contactNumber = contactNumber;
}
public DefectiveComponentInfo getDefectiveComponentInfo() {
return defectiveComponentInfo;
}
public void setDefectiveComponentInfo(DefectiveComponentInfo defectiveComponentInfo) {
this.defectiveComponentInfo = defectiveComponentInfo;
}
#Override
public String toString() {
return "ProcessRequestInfo [id=" + id + ", userName=" + userName + ", contactNumber=" + contactNumber
+ ", defectiveComponentInfo=" + defectiveComponentInfo + "]";
}
public ProcessRequestInfo(int id, String userName, String contactNumber,
DefectiveComponentInfo defectiveComponentInfo, ZonedDateTime date) {
super();
this.id = id;
this.userName = userName;
this.contactNumber = contactNumber;
this.defectiveComponentInfo = defectiveComponentInfo;
}
public ProcessRequestInfo() {
super();
// TODO Auto-generated constructor stub
}
}
DefectiveComponentInfo.java
import javax.persistence.Embeddable;
#Embeddable
public class DefectiveComponentInfo {
private String componentType;
private String componentName;
private Long quantity;
private String description;
public String getComponentType() {
return componentType;
}
public void setComponentType(String componentType) {
this.componentType = componentType;
}
public String getComponentName() {
return componentName;
}
public void setComponentName(String componentName) {
this.componentName = componentName;
}
public Long getQuantity() {
return quantity;
}
public void setQuantity(Long quantity) {
this.quantity = quantity;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return "DefectiveComponentDetail [componentType=" + componentType + ", componentName=" + componentName
+ ", quantity=" + quantity + ", description=" + description + "]";
}
public DefectiveComponentInfo(String componentType, String componentName, Long quantity, String description) {
super();
this.componentType = componentType;
this.componentName = componentName;
this.quantity = quantity;
this.description = description;
}
public DefectiveComponentInfo() {
super();
// TODO Auto-generated constructor stub
}
}
I have tried few nested json requestbody in postman but the inner class data is getting null.
Below is my json request body which I have tried.
{
"userName" : "sam",
"contactNumber" : "96014587555",
"DefectiveComponentInfo":
[ {
"componentType":"Integral",
"componentName":"Bummper",
"quantity":5,
"description": "Repair product"
}]
}
Thanks in advance!!!
You are almost there. few things to be corrected
{
"userName" : "sam",
"contactNumber" : "96014587555",
"defectiveComponentInfo": {
"componentType":"Integral",
"componentName":"Bummper",
"quantity":5,
"description": "Repair product"
}
}
What i have corrected here
As per #Ausgefuchster already mentioned about the incorrect usage of [] array syntax. Removed it.
Your property name is defectiveComponentInfo not capital D.
Try this:
"DefectiveComponentInfo":
{
"componentType": "Integral",
"componentName": "Bummper",
"quantity": 5,
"description": "Repair product"
}
Because you're using [] but these indicate a list.
Is there any way to make a super-class document (e.g. index name = user) and create two child classes (Admin, Guest) to save all this to user index but with different fields? E.g. Add to super-class field type and based on this field fetch right entity? ELK 7.19, Spring Data 4.3.1.
You can do that. Make the base class abstract. I have this in a test setup with the following classes:
#Document(indexName = "type-hints")
public abstract class BaseClass {
#Id
private String id;
#Field(type = FieldType.Text)
private String baseText;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBaseText() {
return baseText;
}
public void setBaseText(String baseText) {
this.baseText = baseText;
}
#Override
public String toString() {
return "BaseClass{" +
"id='" + id + '\'' +
", baseText='" + baseText + '\'' +
'}';
}
}
public class DerivedOne extends BaseClass {
#Field(type = FieldType.Text)
private String derivedOne;
public String getDerivedOne() {
return derivedOne;
}
public void setDerivedOne(String derivedOne) {
this.derivedOne = derivedOne;
}
#Override
public String toString() {
return "DerivedOne{" +
"derivedOne='" + derivedOne + '\'' +
"} " + super.toString();
}
}
public class DerivedTwo extends BaseClass {
#Field(type = FieldType.Text)
private String derivedTwo;
public String getDerivedTwo() {
return derivedTwo;
}
public void setDerivedTwo(String derivedTwo) {
this.derivedTwo = derivedTwo;
}
#Override
public String toString() {
return "DerivedTwo{" +
"derivedTwo='" + derivedTwo + '\'' +
"} " + super.toString();
}
}
interface TypeHintRepository extends ElasticsearchRepository<BaseClass, String> {
SearchHits<? extends BaseClass> searchAllBy();
}
#RestController
#RequestMapping("/typehints")
public class TypeHintController {
private static final Logger LOGGER = LoggerFactory.getLogger(TypeHintController.class);
private final TypeHintRepository repository;
public TypeHintController(TypeHintRepository repository) {
this.repository = repository;
}
#GetMapping
public void test() {
List<BaseClass> docs = new ArrayList<>();
DerivedOne docOne = new DerivedOne();
docOne.setId("one");
docOne.setBaseText("baseOne");
docOne.setDerivedOne("derivedOne");
docs.add(docOne);
DerivedTwo docTwo = new DerivedTwo();
docTwo.setId("two");
docTwo.setBaseText("baseTwo");
docTwo.setDerivedTwo("derivedTwo");
docs.add(docTwo);
repository.saveAll(docs);
SearchHits<? extends BaseClass> searchHits = repository.searchAllBy();
for (SearchHit<? extends BaseClass> searchHit : searchHits) {
LOGGER.info(searchHit.toString());
}
}
}
hi i'm working with spring boot and rest in my project and i estableshed a relation ManyToOne between two enteties but i'm unable to send the postman request to add a mission along with its category i'm not even sure that the two enteties are correctly related
he are the two entities and the contoller
the mission etity
#Entity
#Table(name="missions")
public class Mission {
public Mission() {
}
public Mission(int id, String state, String adresse, int etatMission, String image, List<Categorie> categories,
String ville, int duree, String description, String domaine) {
this.id = id;
this.state = state;
this.adresse = adresse;
this.etatMission = etatMission;
this.image = image;
this.categories = categories;
this.ville = ville;
this.duree = duree;
this.description = description;
this.domaine = domaine;
}
public List<Categorie> getCategories() {
return categories;
}
public void setCategories(List<Categorie> categories) {
this.categories = categories;
}
public String getVille() {
return ville;
}
public void setVille(String ville) {
this.ville = ville;
}
public Mission(Map<String,Object> userMap) {
if (userMap.get("id") != null)
this.id = (int )userMap.get("id");
this.state = (String) userMap.get("state");
this.duree = (int) userMap.get("duree");
this.domaine = (String) userMap.get("domaine");
this.description = (String) userMap.get("description");
this.ville=(String) userMap.get("ville");
this.adresse=(String) userMap.get("adresse");
this.etatMission=(int) userMap.get("etatMission");
this.image=(String) userMap.get("image");
this.categories=(List<Categorie>) userMap.get("categories");
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String state;
private String adresse;
private int etatMission;
private String image;
#OneToMany(mappedBy="mission",cascade=CascadeType.ALL)
private List<Categorie> categories;
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
private String ville;
public int getEtatMission() {
return etatMission;
}
public void setEtatMission(int etatMission) {
this.etatMission = etatMission;
}
private int duree;
private String description;
private String domaine;
public String getDomaine() {
return domaine;
}
public void setDomaine(String domaine) {
this.domaine = domaine;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAdresse() {
return adresse;
}
public void setAdresse(String adresse) {
this.adresse = adresse;
}
#Override
public String toString() {
return "Mission [id=" + id + ", state=" + state + ", duree=" + duree + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public int getDuree() {
return duree;
}
public void setDuree(int duree) {
this.duree = duree;
}
public void add(Categorie cat) {
if (categories == null) {
categories = new ArrayList<>();
}
categories.add(cat);
cat.setMission(this);
}
}
the category entety
#Entity
#Table(name="categorie")
public class Categorie {
public Categorie() {
}
public Categorie(Map<String, Object> catMap) {
this.id=(int) catMap.get("id");
this.nom = (String) catMap.get("nom");
this.mission =(Mission) catMap.get("mission_id") ;
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id ;
private String nom;
#ManyToOne
#JoinColumn(name="mission_id",referencedColumnName="id")
private Mission mission;
public Categorie(int id, String nom, Mission mission) {
this.id = id;
this.nom = nom;
this.mission = mission;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
#Override
public String toString() {
return "Categorie [nom=" + nom + "]";
}
public Mission getMission() {
return mission;
}
public void setMission(Mission mission) {
this.mission = mission;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
here's the controller for mission
package ma.ac.emi.MinuteBrico.Controllers;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import ma.ac.emi.MinuteBrico.Services.MissionServices;
import ma.ac.emi.MinuteBrico.Models.Mission;
#RestController
public class MissionController {
#Autowired
private MissionServices missionService;
#CrossOrigin
#GetMapping("/missions")
public List<Mission> index(){
return missionService.findAll();
}
#CrossOrigin
#GetMapping("/missions/{id}")
public Optional<Mission> indexById(#PathVariable String id){
int missionId = Integer.parseInt(id);
return missionService.findById(missionId);
}
#CrossOrigin()
#PostMapping("/missions")
public String create(#RequestBody Map<String, Object> missionMap) {
System.out.println(missionMap);
Mission mission = new Mission(missionMap);
missionService.savemission(mission);
return "Mission ajouté";
}
}
package ma.ac.emi.MinuteBrico.Repositories;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import ma.ac.emi.MinuteBrico.Models.Mission;
public interface MissionRepository extends JpaRepository<Mission,Integer> {
}
the postman request
{
"state": "Urgent",
"adresse": "Av ben drisse",
"etatMission": 0,
"image": "assets/Brand.jpeg",
"ville": "Chefchaouen",
"duree": 480000,
"description": "je veux quelqu\\'un pour me faire une cuisne",
"domaine": "Plomberie",
"categories":[
{
"id":15,
"nom":"Menuiserie",
"mission":{
"field":"value"
}
}
]
}
try to add #ManyToOne(cascade = CascadeType.ALL)
I use spring-boot-data-jpa-2.0 to get data from db. A table has many-to-one relation, and the query speed is too slow, 1000 lines data with foreign key will cost 15s, but by native sql it will cost only 0.07s. I search the issue and found that it is because 1+n problem.
Some solution that says use 'join fetch' in hql can solve. When I use the 'join fetch' in hql, query speed not change.
The system designed as a pure rest service, with spring boot framework.
contract entity
import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "MA_CONTRACTINFO_B")
public class MaContractinfoB implements java.io.Serializable {
// Fields
private String contractcd;
private MaDepartmentB maDepartmentB;
private Double contractid;
private String contractnm;
private String partya;
private String deputycontract;
private String prjtype;
private Double fundt;
private String bustype;
private String contractstatus;
private Double contractyear;
private String fundratio;
private LocalDateTime signdate;
private String prj;
private LocalDateTime loaddate;
private String udep;
private Double fundaccont;
private Double receipt;
private Double fundacctot;
private Double receiptot;
private String loc;
private String riskasscd;
private String rm;
private String pm;
private Double fundaccrec;
private String adminleader;
private String techleader;
private String leader;
private String progress;
private String cashadmin;
private String timetask;
private String contracttp;
// Constructors
/** default constructor */
public MaContractinfoB() {
}
/** minimal constructor */
public MaContractinfoB(String contractcd) {
this.contractcd = contractcd;
}
/** full constructor */
public MaContractinfoB(String contractcd, MaDepartmentB maDepartmentB, Double contractid, String contractnm,
String partya, String deputycontract, String prjtype, Double fundt, String bustype, String contractstatus,
Double contractyear, String fundratio, LocalDateTime signdate, String prj, LocalDateTime loaddate,
String udep, Double fundaccont, Double receipt, Double fundacctot, Double receiptot, String loc,
String riskasscd, String rm, String pm, Double fundaccrec, String adminleader, String techleader,
String leader, String progress, String cashadmin, String timetask, String contracttp) {
this.contractcd = contractcd;
this.maDepartmentB = maDepartmentB;
this.contractid = contractid;
this.contractnm = contractnm;
this.partya = partya;
this.deputycontract = deputycontract;
this.prjtype = prjtype;
this.fundt = fundt;
this.bustype = bustype;
this.contractstatus = contractstatus;
this.contractyear = contractyear;
this.fundratio = fundratio;
this.signdate = signdate;
this.prj = prj;
this.loaddate = loaddate;
this.udep = udep;
this.fundaccont = fundaccont;
this.receipt = receipt;
this.fundacctot = fundacctot;
this.receiptot = receiptot;
this.loc = loc;
this.riskasscd = riskasscd;
this.rm = rm;
this.pm = pm;
this.fundaccrec = fundaccrec;
this.adminleader = adminleader;
this.techleader = techleader;
this.leader = leader;
this.progress = progress;
this.cashadmin = cashadmin;
this.timetask = timetask;
this.contracttp = contracttp;
}
// Property accessors
#Id
#Column(name = "CONTRACTCD", unique = true, nullable = false)
public String getContractcd() {
return this.contractcd;
}
public void setContractcd(String contractcd) {
this.contractcd = contractcd;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "DEPID")
public MaDepartmentB getMaDepartmentB() {
return this.maDepartmentB;
}
public void setMaDepartmentB(MaDepartmentB maDepartmentB) {
this.maDepartmentB = maDepartmentB;
}
#Column(name = "CONTRACTID", precision = 38, scale = 8)
public Double getContractid() {
return this.contractid;
}
public void setContractid(Double contractid) {
this.contractid = contractid;
}
#Column(name = "CONTRACTNM")
public String getContractnm() {
return this.contractnm;
}
public void setContractnm(String contractnm) {
this.contractnm = contractnm;
}
#Column(name = "PARTYA")
public String getPartya() {
return this.partya;
}
public void setPartya(String partya) {
this.partya = partya;
}
#Column(name = "DEPUTYCONTRACT")
public String getDeputycontract() {
return this.deputycontract;
}
public void setDeputycontract(String deputycontract) {
this.deputycontract = deputycontract;
}
#Column(name = "PRJTYPE")
public String getPrjtype() {
return this.prjtype;
}
public void setPrjtype(String prjtype) {
this.prjtype = prjtype;
}
#Column(name = "FUNDT", precision = 38, scale = 8)
public Double getFundt() {
return this.fundt;
}
public void setFundt(Double fundt) {
this.fundt = fundt;
}
#Column(name = "BUSTYPE")
public String getBustype() {
return this.bustype;
}
public void setBustype(String bustype) {
this.bustype = bustype;
}
#Column(name = "CONTRACTSTATUS")
public String getContractstatus() {
return this.contractstatus;
}
public void setContractstatus(String contractstatus) {
this.contractstatus = contractstatus;
}
#Column(name = "CONTRACTYEAR", precision = 38, scale = 8)
public Double getContractyear() {
return this.contractyear;
}
public void setContractyear(Double contractyear) {
this.contractyear = contractyear;
}
#Column(name = "FUNDRATIO")
public String getFundratio() {
return this.fundratio;
}
public void setFundratio(String fundratio) {
this.fundratio = fundratio;
}
#Column(name = "SIGNDATE", length = 11)
public LocalDateTime getSigndate() {
return this.signdate;
}
public void setSigndate(LocalDateTime signdate) {
this.signdate = signdate;
}
#Column(name = "PRJ")
public String getPrj() {
return this.prj;
}
public void setPrj(String prj) {
this.prj = prj;
}
#Column(name = "LOADDATE", length = 11)
public LocalDateTime getLoaddate() {
return this.loaddate;
}
public void setLoaddate(LocalDateTime loaddate) {
this.loaddate = loaddate;
}
#Column(name = "UDEP")
public String getUdep() {
return this.udep;
}
public void setUdep(String udep) {
this.udep = udep;
}
#Column(name = "FUNDACCONT", precision = 38, scale = 8)
public Double getFundaccont() {
return this.fundaccont;
}
public void setFundaccont(Double fundaccont) {
this.fundaccont = fundaccont;
}
#Column(name = "RECEIPT", precision = 38, scale = 8)
public Double getReceipt() {
return this.receipt;
}
public void setReceipt(Double receipt) {
this.receipt = receipt;
}
#Column(name = "FUNDACCTOT", precision = 38, scale = 8)
public Double getFundacctot() {
return this.fundacctot;
}
public void setFundacctot(Double fundacctot) {
this.fundacctot = fundacctot;
}
#Column(name = "RECEIPTOT", precision = 38, scale = 8)
public Double getReceiptot() {
return this.receiptot;
}
public void setReceiptot(Double receiptot) {
this.receiptot = receiptot;
}
#Column(name = "LOC")
public String getLoc() {
return this.loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
#Column(name = "RISKASSCD")
public String getRiskasscd() {
return this.riskasscd;
}
public void setRiskasscd(String riskasscd) {
this.riskasscd = riskasscd;
}
#Column(name = "RM")
public String getRm() {
return this.rm;
}
public void setRm(String rm) {
this.rm = rm;
}
#Column(name = "PM")
public String getPm() {
return this.pm;
}
public void setPm(String pm) {
this.pm = pm;
}
#Column(name = "FUNDACCREC", precision = 38, scale = 8)
public Double getFundaccrec() {
return this.fundaccrec;
}
public void setFundaccrec(Double fundaccrec) {
this.fundaccrec = fundaccrec;
}
#Column(name = "ADMINLEADER")
public String getAdminleader() {
return this.adminleader;
}
public void setAdminleader(String adminleader) {
this.adminleader = adminleader;
}
#Column(name = "TECHLEADER")
public String getTechleader() {
return this.techleader;
}
public void setTechleader(String techleader) {
this.techleader = techleader;
}
#Column(name = "LEADER", length = 20)
public String getLeader() {
return this.leader;
}
public void setLeader(String leader) {
this.leader = leader;
}
#Column(name = "PROGRESS", length = 1000)
public String getProgress() {
return this.progress;
}
public void setProgress(String progress) {
this.progress = progress;
}
#Column(name = "CASHADMIN", length = 20)
public String getCashadmin() {
return this.cashadmin;
}
public void setCashadmin(String cashadmin) {
this.cashadmin = cashadmin;
}
#Column(name = "TIMETASK", length = 2000)
public String getTimetask() {
return this.timetask;
}
public void setTimetask(String timetask) {
this.timetask = timetask;
}
#Column(name = "CONTRACTTP", length = 50)
public String getContracttp() {
return this.contracttp;
}
public void setContracttp(String contracttp) {
this.contracttp = contracttp;
}
/**
* toString
*
* #return String
*/
#Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getClass().getName()).append("#").append(Integer.toHexString(hashCode())).append(" [");
buffer.append("contractcd").append("='").append(getContractcd()).append("' ");
buffer.append("maDepartmentB").append("='").append(getMaDepartmentB()).append("' ");
buffer.append("contractid").append("='").append(getContractid()).append("' ");
buffer.append("contractnm").append("='").append(getContractnm()).append("' ");
buffer.append("partya").append("='").append(getPartya()).append("' ");
buffer.append("deputycontract").append("='").append(getDeputycontract()).append("' ");
buffer.append("prjtype").append("='").append(getPrjtype()).append("' ");
buffer.append("fundt").append("='").append(getFundt()).append("' ");
buffer.append("bustype").append("='").append(getBustype()).append("' ");
buffer.append("contractstatus").append("='").append(getContractstatus()).append("' ");
buffer.append("contractyear").append("='").append(getContractyear()).append("' ");
buffer.append("fundratio").append("='").append(getFundratio()).append("' ");
buffer.append("signdate").append("='").append(getSigndate()).append("' ");
buffer.append("prj").append("='").append(getPrj()).append("' ");
buffer.append("loaddate").append("='").append(getLoaddate()).append("' ");
buffer.append("udep").append("='").append(getUdep()).append("' ");
buffer.append("fundaccont").append("='").append(getFundaccont()).append("' ");
buffer.append("receipt").append("='").append(getReceipt()).append("' ");
buffer.append("fundacctot").append("='").append(getFundacctot()).append("' ");
buffer.append("receiptot").append("='").append(getReceiptot()).append("' ");
buffer.append("loc").append("='").append(getLoc()).append("' ");
buffer.append("riskasscd").append("='").append(getRiskasscd()).append("' ");
buffer.append("rm").append("='").append(getRm()).append("' ");
buffer.append("pm").append("='").append(getPm()).append("' ");
buffer.append("fundaccrec").append("='").append(getFundaccrec()).append("' ");
buffer.append("adminleader").append("='").append(getAdminleader()).append("' ");
buffer.append("techleader").append("='").append(getTechleader()).append("' ");
buffer.append("leader").append("='").append(getLeader()).append("' ");
buffer.append("progress").append("='").append(getProgress()).append("' ");
buffer.append("cashadmin").append("='").append(getCashadmin()).append("' ");
buffer.append("timetask").append("='").append(getTimetask()).append("' ");
buffer.append("contracttp").append("='").append(getContracttp()).append("' ");
buffer.append("]");
return buffer.toString();
}
}
department entity
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "MA_DEPARTMENT_B")
public class MaDepartmentB implements java.io.Serializable {
// Fields
private Long id;
private String name;
private String leader;
private Set<MaContractinfoB> maContractinfoBs = new HashSet<MaContractinfoB>(0);
private Set<MaContraimB> maContraimBs = new HashSet<MaContraimB>(0);
// Constructors
/** default constructor */
public MaDepartmentB() {
}
/** minimal constructor */
public MaDepartmentB(Long id) {
this.id = id;
}
/** full constructor */
public MaDepartmentB(Long id, String name, String leader, Set<MaContractinfoB> maContractinfoBs,
Set<MaContraimB> maContraimBs) {
this.id = id;
this.name = name;
this.leader = leader;
this.maContractinfoBs = maContractinfoBs;
this.maContraimBs = maContraimBs;
}
// Property accessors
#Id
#Column(name = "ID", unique = true, nullable = false, precision = 10, scale = 0)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "NAME")
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "LEADER")
public String getLeader() {
return this.leader;
}
public void setLeader(String leader) {
this.leader = leader;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "maDepartmentB")
public Set<MaContractinfoB> getMaContractinfoBs() {
return this.maContractinfoBs;
}
public void setMaContractinfoBs(Set<MaContractinfoB> maContractinfoBs) {
this.maContractinfoBs = maContractinfoBs;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "maDepartmentB")
public Set<MaContraimB> getMaContraimBs() {
return this.maContraimBs;
}
public void setMaContraimBs(Set<MaContraimB> maContraimBs) {
this.maContraimBs = maContraimBs;
}
/**
* toString
*
* #return String
*/
#Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getClass().getName()).append("#").append(Integer.toHexString(hashCode())).append(" [");
buffer.append("id").append("='").append(getId()).append("' ");
buffer.append("name").append("='").append(getName()).append("' ");
buffer.append("leader").append("='").append(getLeader()).append("' ");
buffer.append("maContractinfoBs").append("='").append(getMaContractinfoBs()).append("' ");
buffer.append("maContraimBs").append("='").append(getMaContraimBs()).append("' ");
buffer.append("]");
return buffer.toString();
}
}
jparepository
public interface MaContractinfoBRepository extends JpaRepository<MaContractinfoB, Long> {
#Query("from MaContractinfoB c join fetch c.maDepartmentB")
List<MaContractinfoB> findAll();
#Query("select contractnm from MaContractinfoB")
List<String> findAllName();
// #Query("from MaContractinfoB c join fetch c.maDepartmentB")
// List test();
}
In MaContractinfoBRepository, When I use findAllName function, it will immediately return 1000 contract names in 0.05s. When I use findAll, it will cost 15s to get 1000 data with department entity, even I add join fetch. But if I get it by native sql in db tool such as navicat, it will cost only 0.07s.
Is any keypoint I missed? How to query the MaContractinfoB table not so slowly?
This is happening because internally with 'fetch' command also hibernate is lazy loading all the rows of Department entity for each Contract id whenever you call the findAll() method. So if there are n rows in Department for 1 Contract and in total there are m Contracts then the total number of calls to the database would be 'm * n'.
One way around this is by using DTO projections. Data Transfer Objects is an easy way to define all the required columns in one query and hit the database for once.
I have found this article useful which shows multiple ways of writing DTO projections.
https://thoughts-on-java.org/dto-projections/
One of the mentioned way is: Using JPQL you can use a constructor expression to define a constructor call with the keyword new followed by the fully classified class name of your DTO and a list of constructor parameters in curly braces.
Something like this:
TypedQuery<ContractWithDepartmentDetails> q = em.createQuery(
"SELECT new com.practice.model.ContractWithDepartmentDetails(c.id, c.name, d.name) FROM contract c JOIN c.department d",
ContractWithDepartmentDetails.class);
In my spring boot project I created a Repository interface (which extends CRUDRepository) and an Entity class of the Table in my DB.
This is my Repo:
#Repository
public interface AuthPaymentDao extends CrudRepository<TFraudCard,String> {
#Query("SELECT t FROM TFraudCard t where t.tokenNumber = (?1)")
TFraudCard findByTokenNumber(String tokenNumber);
}
This is my Entity Class (TOKEN_NUMBER is the primary Key in the TFRAUDCARD TABLE):
#Entity
#Table(name = "TFRAUDCARD")
public class TFraudCard {
#Id
#Column(name="TOKEN_NUMBER")
private String tokenNumber;
#Column(name="TRANSACTIONNUMBER")
private int transactionNumber;
#Column(name="CARDNUMBER")
private int cardNumber;
#Column(name="DATEADDED", insertable = false, updatable = false, nullable = false)
private Timestamp dateAdded;
#Column(name="CALLINGENTITY", nullable = false)
private String callingEntity;
#Column(name="ACCOUNTID")
private String accountId;
#Column(name="ROUTINGNUMBER")
private String routingNumber;
#Column(name="BANKACCOUNTNUMBER")
private String bankAccountNumber;
#Column(name="COMMENTS")
private String comments;
#Column(name="USERID")
private String userId;
#Column(name="REMOVEDATE")
private Timestamp removeDate;
public String getTokenNumber() {
return tokenNumber;
}
public void setTokenNumber(String tokenNumber) {
this.tokenNumber = tokenNumber;
}
public int getTransactionNumber() {
return transactionNumber;
}
public void setTransactionNumber(int transactionNumber) {
this.transactionNumber = transactionNumber;
}
public int getCardNumber() {
return cardNumber;
}
public void setCardNumber(int cardNumber) {
this.cardNumber = cardNumber;
}
public Timestamp getDateAdded() {
return dateAdded;
}
public void setDateAdded(Timestamp dateAdded) {
this.dateAdded = dateAdded;
}
public String getCallingEntity() {
return callingEntity;
}
public void setCallingEntity(String callingEntity) {
this.callingEntity = callingEntity;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public String getRoutingNumber() {
return routingNumber;
}
public void setRoutingNumber(String routingNumber) {
this.routingNumber = routingNumber;
}
public String getBankAccountNumber() {
return bankAccountNumber;
}
public void setBankAccountNumber(String bankAccountNumber) {
this.bankAccountNumber = bankAccountNumber;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Timestamp getRemoveDate() {
return removeDate;
}
public void setRemoveDate(Timestamp removeDate) {
this.removeDate = removeDate;
}
public TFraudCard() {
super();
}
public TFraudCard(String tokenNumber, int transactionNumber, int cardNumber, Timestamp dateAdded,
String callingEntity, String accountId, String routingNumber, String bankAccountNumber, String comments,
String userId, Timestamp removeDate) {
super();
this.tokenNumber = tokenNumber;
this.transactionNumber = transactionNumber;
this.cardNumber = cardNumber;
this.dateAdded = dateAdded;
this.callingEntity = callingEntity;
this.accountId = accountId;
this.routingNumber = routingNumber;
this.bankAccountNumber = bankAccountNumber;
this.comments = comments;
this.userId = userId;
this.removeDate = removeDate;
}
#Override
public String toString() {
return "TFraudCard [tokenNumber=" + tokenNumber + ", transactionNumber=" + transactionNumber + ", cardNumber="
+ cardNumber + ", dateAdded=" + dateAdded + ", callingEntity=" + callingEntity + ", accountId="
+ accountId + ", routingNumber=" + routingNumber + ", bankAccountNumber=" + bankAccountNumber
+ ", comments=" + comments + ", userId=" + userId + ", removeDate=" + removeDate + "]";
}
}
My Service Class:
Autowiring the DAO instance inside my Service Class:
Implementing the DAO instance inside a Method in the Service Class:
private void fraudCheck(PaymentDetail paymentDetail) throws RegularPaymentBusinessException {
logger.info("INSIDE FRAUD CHECK METHOD");
String pmtInd=paymentDetail.getPmtInd();
logger.info("pmtInd: " + pmtInd);
String tokenizedCardNum=paymentDetail.getTokenizedCardNum();
logger.info("tokenizedCardNum: " + tokenizedCardNum);
if(pmtInd.equalsIgnoreCase(VepsConstants.GIFT_CARD_IDENTIFIER) || pmtInd.equalsIgnoreCase(VepsConstants.CREDIT_CARD_IDENTIFIER) || pmtInd.equalsIgnoreCase(VepsConstants.DEBIT_CARD_IDENTIFIER)) {
logger.info("INSIDE CARD CHECK");
TFraudCard fraudCard = authPaymentDao.findByTokenNumber(tokenizedCardNum);
logger.info("fraudCard Details: " + fraudCard.toString());
if(fraudCard!=null) {
logger.info("INSIDE EXCEPTION FLOW FOR CARD FRAUD CHECK");
throw new RegularPaymentBusinessException(VepsConstants._9966, VepsConstants._9966_MESSAGE, VepsConstants.FAILURE);
}
}
}
Even though I pass the same token Number (tokenizedCardNumber) in my method as the data in the TOKEN_NUMBER column of my TFRAUDCARD table I still get a NullPointerException when I try to print a toString() of the Entity Object.
Here is the NullPointerException on my cloudFoundry logs (Click on it to see zoomed image) :
I'm providing the DB details in my dev properties file:
I have gone over every scenario in my head for why it breaks but I still can't come up with an answer. I'm using my variable marked with #Id i.e. the Primary Key for my find() method in the Repository.
I'm also adding a #Query annotation just to be even more specific.
It still does not work.