How to implement group by with sum of multiple fields in java - java

Controller class:
#RestController
#RequestMapping(value = "/api/v1/")
public class TestController {
#Autowired
TestService testService;
#GetMapping(value = "test")
public List<Bean> getDetails() {
return testService.getDetails();
}
}
Service class:
#Service
public class TestService {
#Autowired
BeanRepository beanRepository;
public List<Bean> getDetails() {
List<Bean> res = new ArrayList<>();
try{
List<BeanEntity> beans = beanRepository.findAllApplications();
for(BeanEntity beanEntity : beans) {
Bean bean = new Bean();
BeanUtils.copyProperties(beanEntity, bean);
if(beanEntity.getDesc().contains("Motor") || beanEntity.getDesc().contains("Nut")){
bean.setName("A");
} else if (beanEntity.getDesc().contains("Bolt") || beanEntity.getDesc().contains("Engine")) {
bean.setName("B");
} else {
bean.setName("C");
}
res.add()
}
} catch(Exception e) {
throw new e;
}
}
}
Entity class:
#Getter
#Setter
#NoArgConstructor
#AllArgConstructor
#Entity
public class BeanEntity implements Serializable {
private static final long serialVersionID = 3269743987697633760L;
#Id
#Column(name = "ApplicationID", nullable = false, unique = true)
public String application_id;
#Column(name= "Description")
public String desc;
#Column(name = "Status")
public String status;
#Column(name ="Approved")
public int approved;
#Column(name ="Declined")
public int declined;
}
Bean class:
#Getter
#Setter
#NoArgConstructor
#AllArgConstructor
public class Bean {
public String application_id;
public String desc;
public String status;
public int approved;
public int declined;
public String name;
}
Repository class:
#Repository
public interface BeanRepository extends JpaRepository<BeanEntity, String> {
#Query(name = "select * from abc", nativeQuery = true)
List<BeanEntity> findAllApplications();
}
Below is the Current Response i am getting from above code:
[
{
"application_id" : "12345",
"desc": "Motor",
"status": "active",
"approved": 1,
"declined": 0,
"name": "A"
},
{
"application_id" : "14785",
"desc": "Nut",
"status": "active",
"approved": 0,
"declined": 1,
"name": "A"
},
{
"application_id" : "15974",
"desc": "Bolt",
"status": "not-active",
"approved": 1,
"declined": 0,
"name": "B"
},
{
"application_id" : "36985",
"desc": "Engine",
"status": "active",
"approved": 1,
"declined": 0,
"name": "B"
},
{
"application_id" : "78945",
"desc": "Filter",
"status": "active",
"approved": 1,
"declined": 0,
"name": "C"
},
{
"application_id" : "45612",
"desc": "AC",
"status": "active",
"approved": 0,
"declined": 1,
"name": "C"
}
]
Expected Response i am looking for:
[
{
"name": "A",
"approved": 1,
"declined": 1
},
{
"name": "B",
"approved": 2,
"declined": 0
},
{
"name": "C",
"approved": 1,
"declined": 1
}
]
I am in beginner phase of learning java, How to implement group by with sum of multiple fields in java.
Can someone help me how i can achieve the expected response.

Related

Infinite Loop Created When I want to Create an Organization Diagram Using Java Spring Boot

I try to do a project where I can show data Like this:
{
"vp2": {
"parentName": "ceo1",
"isParent": 0,
"hasChild": 0,
"child": []
}
}
Here My data are:
[
{
"entityName": "ceo1",
"parentId": 0,
"id": 1
},
{
"entityName": "ceo2",
"parentId": 0,
"id": 2
},
{
"entityName": "vp1",
"parentId": 1,
"id": 3
},
{
"entityName": "vp2",
"parentId": 1,
"id": 4
},
{
"entityName": "vp3",
"parentId": 1,
"id": 5
},
{
"entityName": "vp4",
"parentId": 2,
"id": 6
},
{
"entityName": "ceo3",
"parentId": 0,
"id": 7
},
{
"entityName": "ceo4",
"parentId": 0,
"id": 8
}
]
I want to show the data using map<Entity Name, DataModel>. Here DataModel's code is
#Data
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class DemoModel {
private String parentName;
private int isParent;
private int hasChild;
public List<Map<String, DemoModel>> child;
}
When there is no child, I get it properly. But when there is a child my function can not work. It gives infinite recursion problems. Here is my service function code
public Map<String, DemoModel> recursiveHelperFunction(int Id, List<DemoEntity> fullEntityList, List<Map<String, DemoModel>> modelList) {
Map<String, DemoModel> map = new HashMap<>();
DemoEntity demo = demoRepository.findById((long) Id).get();
DemoModel demoModel = new DemoModel();
String entityName = demo.getEntityName();
int parentId = (int) demo.getParentId();
if (Objects.equals(parentId, 0)) {
demoModel.setIsParent(1);
demoModel.setParentName("");
} else {
demoModel.setIsParent(0);
demoModel.setHasChild(0);
demoModel.setParentName(fullEntityList.get((int) demo.getParentId() - 1).getEntityName());
}
Iterator<DemoEntity> itr = fullEntityList.iterator();
while (itr.hasNext()) {
DemoEntity demo1 = itr.next();
int demo1Id = (int) demo1.getParentId();
int Id1 = (int) Id;
if (demo1Id == Id1) {
demoModel.setHasChild(1);
String demo1Entity = demo1.getEntityName();
try {
Map<String, DemoModel> map1 = recursiveHelperFunction((int) demo1.getId(), fullEntityList, modelList);
log.info("maps :{}", map1);
modelList.add(map1); //got error here
//demoModel.child.add(map1);
log.info("maps equal:??: {}", modelList.contains(map1));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
demoModel.setChild(modelList);
map.put(entityName, demoModel);
return map;
}
I call this helper recursive function here:
public Map<String, DemoModel> getDataById(int Id) {
List<DemoEntity> list = demoRepository.findAll();
List<Map<String, DemoModel>> modelList = new ArrayList<>();
return recursiveHelperFunction(Id, list, modelList);
}
Here, the DemoEntity code is:
#Entity
#Data
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class DemoEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long Id;
#Column(unique = true)
private String entityName;
private long parentId;
}
How can I stop this infinite recursive problem?

Spring REST API, custom entity fields in the response

I'm working in a REST API (Java, SpringBoot, QueryDsl...) and I would like to customize the fields that I have in the result. By default I'm obtaining all fields of the entity but the fields that I need depends on the request. This should be something dynamic.
As far as I know, using projections I can obtain something like this but I have to declare previously the projection and I would like to work with something dynamic not static. On the other hand I have seen than something like GraphQL allows this behaviour but I would have to refactor everything.
Has anyone had this problem before?
This is my code:
BaseRestCRUDController
public abstract class BaseRestCRUDController<T extends EntityBase, V extends BaseDTO> {
#GetMapping("/list")
public ResponseEntity<List<V>> findAll(Predicate predicate, Pageable pageable) {
log.info("FindAll");
return new ResponseEntity(getCRUDService().findAll(predicate, pageable), HttpStatus.OK);
}
}
ExampleController
#RestController
#RequestMapping("/api/example")
public class ExampleController
extends BaseRestCRUDController<Example, ExampleDTO> {
#Autowired
private ExampleService ExampleService;
#Override
public ResponseEntity<List<ExampleDTO>> findAll(
#QuerydslPredicate(root = Example.class) Predicate predicate, Pageable pageable) {
return super.findAll(predicate, pageable);
}
#Override
protected CRUDService<Example, ExampleDTO> getCRUDService() {
return ExampleService;
}
}
Example (Entity)
public class Example {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "creation_date")
private Instant creationDate;
#Column(name = "last_update")
private Instant lastUpdate;
#Column(name = "erasure_date")
private Instant erasureDate;
}
http://localhost:8080/api/example/list?name=test&page=0&size=5&sort=id,desc
http://localhost:8080/api/example/list?name=foo&page=1&size=10&sort=id,desc
http://localhost:8080/api/example/list?page=0&size=2&sort=id,asc
[
{
"id": 1,
"name": "e1",
"creationDate": "2021-11-15T23:00:00Z",
"lastUpdate": null,
"erasureDate": null
},
{
"id": 2,
"name": "e2",
"creationDate": "2021-11-15T23:00:00Z",
"lastUpdate": null,
"erasureDate": null
},
{
"id": 3,
"name": "e3",
"creationDate": "2021-11-15T23:00:00Z",
"lastUpdate": null,
"erasureDate": null
}
]
How can I obtain something like this without use projections?
http://localhost:8080/api/example/list?fields=id,name&page=1&size=10&sort=id,desc
[
{
"id": 1,
"name": "e1"
},
{
"id": 2,
"name": "e2"
},
{
"id": 3,
"name": "e3"
}
]
http://localhost:8080/api/example/list?fields=name&page=1&size=10&sort=id,desc
[
{
"name": "e1",
},
{
"name": "e2",
},
{
"name": "e3",
}
]
#Ignore
private Instant creationDate;
Try this.
You can use #Ignore on getter,setter or fields.

How map List to an Object with list in mapstructs

How can I use MapStruct to create a mapper that maps a list (my source) to a object with a list (destination)?
My source classes looks like this:
class SourceB {
private String name;
private String lastname;
}
class SourceA {
private Integer id;
private List<SourceB> bs;
}
so I need to transform it to this:
class DestinationA {
private Integer id;
private DestinationAB bs;
}
class DestinationAB {
private List<DestinationB> b;
}
class DestinationB {
private String name;
private String lastname;
}
Expected sample json:
source:
{
"id": 1,
"bs": [
{
"name": "name1",
"lastname": "last1"
},
{
"name": "name2",
"lastname": "last2"
}
]
}
destination:
{
"id": 1,
"bs": {
"b": [
{
"name": "name1",
"lastname": "last1"
},
{
"name": "name2",
"lastname": "last2"
}
]
}
}
It's quite simple. Just put #Mapping annotation with specified source and destination on top of the mapping method.
#Mapper
public interface SourceMapper {
#Mapping(source = "bs", target = "bs.b")
DestinationA sourceAToDestinationA(SourceA sourceA);
}

JSON parser not returning numbers

I have the following JSON structure:
{
"status": "Completed",
"notes": null,
"members": {
"0": {
"year": "2",
"details": {
"id": "14899975",
"anotherId": "11013306"
},
"aName": "Fred",
"amounts": {
"First": 589.48,
"Second": 1000,
"Third": 339.48
}
},
"1": {
"year": "2",
"details": {
"id": "14899976",
"anotherId": "11013306"
},
"aName": "George",
"amounts": {
"First": 222.22,
"Second": 2000,
"Third": 22.22
}
},
"2": {
"year": 1,
"details": {
"id": "14899976",
"anotherId": "11013306"
},
"aName": "Albert",
"amounts": {
"First": 333.33,
"Second": 3000,
"Third": 33.33
},
}
}
}
I am using Spring RESTTemplate and JacksonMapping2HttpMessageConverter, and the following structures to receive the result of parsing the above JSON structure:
#JsonIgnoreProperties(ignoreUnknown = true)
public class Response {
private String status;
private String notes;
private Map<String,Struct1> quotes;
}
#JsonIgnoreProperties(ignoreUnknown = true)
class Struct1 {
private int year;
private Struct2 details;
private String aName;
private Struct3 amounts;
}
#JsonIgnoreProperties(ignoreUnknown = true)
class Struct2 {
private String id;
private String anotherId;
}
#JsonIgnoreProperties(ignoreUnknown = true)
class Struct3 {
private float First;
private float Second;
private float Third;
}
All of these also have appropriate setters and getters for all fields.
My problem is that the number values in Struct3 are not filled in. I've tried making them float, Float, String, and BigDecimal, and the result is either null or 0.0.
I've tried putting a breakpoint in the setter for the first field, hoping
What am I missing? Can the capital letters in the JSON be causing a problem, do I need alternate field names?
It turned out to be the capital letters at the beginning of the field names; I added annotations like #JsonProperty("First") on the line before the getter of the field, and renamed the field to first, and now it's working.

JPA entity resultset duplication with more than one collection

The Contact entity defines relationships to two collections of entity of type email and nickname which exist in two MySQL tables.
My issue is that the result set this returns has duplicated email and nicknames.
{
"contactId": 1,
"givenName": "toast",
"middleName": "brown",
"familyName": "jam",
"dob": "2014-11-19",
"contactEmailAddress": [
{
"emailAddressId": 1,
"emailAddress": "donald.duck#disney.com",
"contactId": 1
},
{
"emailAddressId": 1,
"emailAddress": "donald.duck#disney.com",
"contactId": 1
},
{
"emailAddressId": 2,
"emailAddress": "mickey.mouse#disney.com",
"contactId": 1
},
{
"emailAddressId": 2,
"emailAddress": "mickey.mouse#disney.com",
"contactId": 1
}
],
"contactNickname": [
{
"contactNicknameId": 1,
"nickname": "mm",
"contactId": 1
},
{
"contactNicknameId": 2,
"nickname": "mouse",
"contactId": 1
},
{
"contactNicknameId": 1,
"nickname": "mm",
"contactId": 1
},
{
"contactNicknameId": 2,
"nickname": "mouse",
"contactId": 1
}
]
}
If I remove the ContactNickname collection from the Contact entity the result set is as follows.
{
"contactId": 1,
"givenName": "toast",
"middleName": "brown",
"familyName": "jam",
"dob": "2014-11-19",
"contactEmailAddress": [
{
"emailAddressId": 1,
"emailAddress": "donald.duck#disney.com",
"contactId": 1
},
{
"emailAddressId": 2,
"emailAddress": "mickey.mouse#disney.com",
"contactId": 1
}
]
}
I expected a distinct collection of email address and a distinct collection of nicknames but this is not the case. What am I doing incorrectly.
Using JPA I have mapped the the class as follows.
#Entity
#Table(name="contact")
public class Contact implements Serializable {
#OneToMany(fetch=FetchType.EAGER)
#JoinColumn(name="contact_id")
private Collection<ContactEmailAddress> contactEmailAddress;
#OneToMany(fetch=FetchType.EAGER)
#JoinColumn(name="contact_id")
private Collection<ContactNickname> contactNickname;
public Collection<ContactEmailAddress> getContactEmailAddress(){
return this.contactEmailAddress;
}
public void setContactEmailAddress(Collection<ContactEmailAddress> contactEmailAddress){
this.contactEmailAddress=contactEmailAddress;
}
public Collection<ContactNickname> getContactNickname(){
return this.contactNickname;
}
public void setContactNickname(final Collection<ContactNickname> contactNickname){
this.contactNickname=contactNickname;
}
}
#Entity
#Table(name="contact_email_address")
public class ContactEmailAddress implements Serializable {
#Id
#GeneratedValue
#Column(name="email_address_id")
private int emailAddressId;
#Column(name="email_address")
private String emailAddress;
#Column(name="contact_id")
private int contactId;
public void setContactId(int contactId){
this.contactId=contactId;
}
public int getContactId(){
return this.contactId;
}.
public int getEmailAddressId(){
return emailAddressId;
}
public void setEmailAddressId(final int emailAddressId){
this.emailAddressId=emailAddressId;
}
public String getEmailAddress(){
return emailAddress;
}
public void setEmailAddress(String emailAddress){
this.emailAddress=emailAddress;
}
}
#Entity
#Table(name="contact_nickname")
public class ContactNickname implements Serializable {
#Id
#GeneratedValue
#Column(name="contact_nickname_id")
private int contactNicknameId;
#Column(name="nickname")
private String nickname;
#Column(name="contact_id")
private int contactId;
public int getContactNicknameId(){
return contactNicknameId;
}
public void setContactNicknameId(final int contactNicknameId){
this.contactNicknameId=contactNicknameId;
}
public String getNickname(){
return this.nickname;
}
public void setNickname(String nickname){
this.nickname=nickname;
}
public void setContactId(int contactId){
this.contactId=contactId;
}
public int getContactId(){
return this.contactId;
}
}
Hibernate is running the following when the duplication happens.
SELECT contact0_.contact_id AS contact_1_0_0_,
contact0_.dob AS dob2_0_0_,
contact0_.family_name AS family_n3_0_0_,
contact0_.given_name AS given_na4_0_0_,
contact0_.middle_name AS middle_n5_0_0_,
contactema1_.contact_id AS contact_2_0_1_,
contactema1_.email_address_id AS email_ad1_1_1_,
contactema1_.email_address_id AS email_ad1_1_2_,
contactema1_.contact_id AS contact_2_1_2_,
contactema1_.email_address AS email_ad3_1_2_,
contactnic2_.contact_id AS contact_2_0_3_,
contactnic2_.contact_nickname_id AS contact_1_3_3_,
contactnic2_.contact_nickname_id AS contact_1_3_4_,
contactnic2_.contact_id AS contact_2_3_4_,
contactnic2_.nickname AS nickname3_3_4_
FROM contact contact0_
LEFT OUTER JOIN contact_email_address contactema1_
ON contact0_.contact_id = contactema1_.contact_id
LEFT OUTER JOIN contact_nickname contactnic2_
ON contact0_.contact_id = contactnic2_.contact_id
WHERE contact0_.contact_id =?
Kind regards,
Ian.
If you never want to have duplicates in your collection, you should use Set instead of Collection in your entity.

Categories

Resources