I have two query and resultsets, in the below code I want to showcase that for a particular userGroupCode I have certain userPreference and employee associated with it. I have written the code below code to display the userGroupCode object:
String query1= "SELECT ug.userGroupCode, ug.userGroupDesc, up.userPreference"
+ "FROM dbo.UserGroup_link ug INNER JOIN dbo.UserPreference up ON ug.userGroupCode = up.userGroupCode";
userGroupCode
userGroupDesc
userPreference
A100
Finance
Mumbai
A100
Finance
Bangalore
A200
Supply Chain
Chennai
A201
Marketing
Delhi
A201
Marketing
Kolkata
A300
Health
Indore
String query2= "SELECT ug.userGroupCode, ug.userGroupDesc, emp.employee_id,emp.name,emp.role"
+ "FROM dbo.UserGroup ug INNER JOIN dbo.employee emp ON ug.userGroupCode = emp.userGroupCode";
userGroupCode
userGroupDesc
employee_id
name
role
A100
Finance
101
Foo1
Developer
A100
Finance
101
Foo1
Team Lead
A200
Supply Chain
091
Test1
Manager
A201
Marketing
591
User1
Analyst
A201
Marketing
1001
Boo1
Scrum Master
A300
Health
1001
Boo1
Developer
I have class UserGroupMapping like:
public class UserGroupMapping {
private String userGroupCode;
private String userGroupCode;
private List<String> userPreference;
private List<Employee> emp;
//getter and setter
}
Another class for Employee is:
public class Employee {
private String employee_id;
private String name;
private List<String> role;
//getter and setter
}
In my stored procedure class I am calling these queries with the help of jdbcTemplate.query();
String userCode = null;
List<String> userPreferenceList = new ArrayList<>();
List<UserGroupMapping> userGroupMappingList = new ArrayList<>();
List<UserGroupMapping> userGroupMappingList1 = new ArrayList<>();
UserGroupMapping userGroupMapping = new UserGroupMapping();
List<Employee> employeeList = new ArrayList<>();
Employee emp = new Employee();
UserGroupMapping userGroupMapping1 = new UserGroupMapping();
jdbcTemplate.query(query1, (rs)->{
String user_group_code = rs.getString("userGroupCode");
String user_group_desc = rs.getString("userGroupDesc");
String user_preference = rs.getString("userPreference");
if(userCode == null){
userGroupMapping.setUserGroupCode(user_group_code);
userGroupMapping.setUserGroupDesc(user_group_desc);
userPreferenceList.add(userPreference);
userCode = user_group_code;
} else if (userCode.equals(user_group_code)) {
userPreferenceList.add(userPreference);
} else {
userGroupMapping.setUserPreference(userPreferenceList);
userGroupMappingList.add(userGroupMapping);
userPreferenceList = new ArrayList<>();
userGroupMapping = new userGroupMapping();
userGroupMapping.setUserGroupCode(user_group_code);
userGroupMapping.setUserGroupDesc(user_group_desc);
userPreferenceList.add(userPreference);
userCode = user_group_code;
}});
userCode = null;
userGroupMapping.setUserPreference(userPreferenceList);
userGroupMappingList.add(userGroupMapping);
jdbcTemplate.query(query2, (rs)->{
String user_group_code = rs.getString("userGroupCode");
String user_group_desc = rs.getString("userGroupDesc");
String emp_id = rs.getString("employee_id");
String name = rs.getString("name");
if(userCode == null){
userGroupMapping1.setUserGroupCode(user_group_code);
userGroupMapping1.setUserGroupDesc(user_group_desc);
emp.setId(employeeId);
emp.setName(name);
employeeList.add(emp);
userCode = user_group_code;
} else if (userCode.equals(user_group_code)) {
Employee emp = new Employee();
emp.setId(employeeId);
emp.setName(name);
employeeList.add(emp);
} else {
userGroupMapping1.setEmployee(employeeList);
userGroupMappingList1.add(userGroupMapping1);
employeeList = new ArrayList<>();
userGroupMapping1 = new userGroupMapping();
Employee emp = new Employee();
userGroupMapping1.setUserGroupCode(user_group_code);
userGroupMapping1.setUserGroupDesc(user_group_desc);
emp.setId(employeeId);
emp.setName(name);
employeeList.add(emp);
userCode = user_group_code;
}});
userGroupMapping1.setEmployee(employeeList);
userGroupMappingList1.add(userGroupMapping1);
List<UserGroupMapping> ugList = Stream.concat(userGroupMappingList.stream, userGroupMappingList1.stream).distinct().collect(Collectors.toList())
return ugList;
The problem is that I want my output to be like :
[
{
"userGroupCode" : "A100",
"userGroupDesc" : "Finance",
"userPreference": ["Mumbai","Bangalore"],
"Employee" : [
"employee_id" : "101",
"name" : "Foo1",
"role" : ["Developer","Team Lead"]
]
}
]
After merging the two list I am getting the below output:
[
{
"userGroupCode" : "A100",
"userGroupDesc" : "Finance",
"userPreference": ["Mumbai","Bangalore"],
"Employee" : []
},
{
"userGroupCode" : "A100",
"userGroupDesc" : "Finance",
"userPreference": [],
"Employee" : [
"employee_id" : "101",
"name" : "Foo1",
"role" : []
]
}
]
Could anyone please help me with few things:
How could I embed the role into the Employee object.
How can I merge the table based on userGroupCode and userGroupDesc.
I am feeling the code is not that performance optimised, How could I optimised this code.
Thank you in advance.
Ola,
You can group by using Map taking id as key and value as object ( to be aggregated into) . For example:
if(map.containes(key))
{
get object from map and do Ops.
}
else
{
1. Create new object
2. Do set Ops on Object
3. Add to map.
}
You basically have 2 solutions,
Write a query that returns all results with joins and do filtering in java, quite easy to achieve with 2 maps (one for the UserGroup the other for the Employee.
Write a query and aggregate the duplicates using list in the query itself.
SELECT ug.userGroupCode, ug.userGroupDesc, up.userPreference, emp.employee_id,emp.name,emp.role
FROM dbo.UserGroup_link ug
INNER JOIN dbo.UserPreference up ON ug.userGroupCode = up.userGroupCode
INNER JOIN dbo.employee emp ON ug.userGroupCode = emp.userGroupCode
Then use a RowCallbackHandler to achieve what you want (instead of a ResultSetExtractor.
Map<String, UserGroup> userGroups = new HashMap<>;
Map<Integer, Employee> employees = new HashMap<>;
jdbc.query(query, (rs) -> {
String userGroupCode = rs.getString("userGroupCode");
String emp_id = rs.getString("employee_id");
UserGroupMapping ugm userGroups.computeIfAbsent(userGroupCode, {
UserGroupMapping ugm1 = new UserGroupMapping();
ugm1.setUserGroupCode(userGroupCode);
ugm1.setUserGroupDesc(rs.getString("userGroupDesc");
ugm1.setUserPreference(new ArrayList<>());
ugm1.getEmployee(new ArrayList<>());
return ugm1;
});
ugm.getUserPreference().add(rs.getString("userPreference"));
Employee emp = employees.computeIfAbsent(emp_id, {
Employee emp1 = new Employee();
emp1.setName(rs.getString("name"));
emp1.setRole(new ArrayList<>());
ugm.getEmployee().add(emp);
return emp1;
});
emp.getRole().add(rs.getString("role"));
});
return userGroups.values();
The above code will get all UserGroupMapping objects from the result including all the Employee instances. The temporary maps are needed to determine if record has already been shown.
Another solution would be to use list in your query and some GROUP BY statement to let the query do part of the aggregation. That way you could make it a bit easier to create an Employee.
Related
I have this Requirement :
Construct each Doctor with their respective Appointments and return a doctorList. Input is Appointment List for whole Hospital.
What I have is the followings:
Two classes given with the following variables.
Class Appointment{
String doctorName;
DateTime startTime;
DateTime endTime;
String speciality;
//Getters-Setters
}
Another Class :
Class Doctor{
String name;
String speciality;
List <Appointment> appointments;
//Getters-Setters
}
Requirement is :
Construct each Doctor with their respective Appointments and return a doctorList.
Input is Appointment List for whole Hospital.
Can some body tell what should be my approach?
I hope this will help you. Use Map to maintain the appointments of each doctor. In the below code you can get the appointment details using the doctor's name.
`//appointments - input list
Map<String, List<Appointment>> map = new HashMap<>();
for(Appointment app : appointments) {
if(!map.containsKey(app.getDoctorName())) {
List<Appointment> li = new ArrayList<>();
li.add(app);
map.put(app.getDoctorName(),li);
} else {
map.get(app.getDoctorName()).add(app);
}
}`
You can use HashMap.
HashMap<Doctor, ArrayList> doctorList = new HashMap<>();
Might not be a good idea in your case mainly because I do not understand what you are trying to achieve.
If you need match doctors with Appointment by both Speciality and Name, then:
Map<String, List<Appointment>> map = appointmentList
.stream()
.collect(Collectors.groupingBy(e -> e.getDoctorName() + e.getSpeciality()));
List<Doctor> doctors = new ArrayList<>();
for (String doctorNameAndSpeciality : map.keySet()) {
List<Appointment> appointments = map.get(doctorNameAndSpeciality);
if (!appointments.isEmpty()) {
Doctor doctor = new Doctor();
Appointment appointment = appointments.get(0);
doctor.setName(appointment.getDoctorName());
doctor.setSpeciality(appointment.getSpeciality());
doctor.addAllAppointments(appointments);
}
}
return doctors;
if you need use only 'name', then just remove 'speciality'
I am having 2 Employee List. One List contains the name and employeeId and the second List contains employeeId and mobile number. employee id is the primary key.
The requirement is to get the List which contains the id, Name, and mobile no using streaming.
public class MainApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
Employee emp1 = new Employee(101, "Shiv1");
Employee emp2 = new Employee(102, "Shiv2");
Employee emp3 = new Employee(103, "Shiv3");
Employee emp4 = new Employee(104, "Shiv4");
Employee emp5 = new Employee(101, 00001);
Employee emp6 = new Employee(101, 00002);
Employee emp7 = new Employee(101, 00003);
Employee emp8 = new Employee(101, 00004);
List<Employee> employeeNameList = new ArrayList<Employee>();
employeeNameList.add(emp1);
employeeNameList.add(emp2);
employeeNameList.add(emp3);
employeeNameList.add(emp4);
List<Employee> employeeMobileList = new ArrayList<Employee>();
employeeMobileList.add(emp5);
employeeMobileList.add(emp6);
employeeMobileList.add(emp7);
employeeMobileList.add(emp8);
employeeNameList.stream()
.filter(item -> item.getId() == 3)
.map(i -> i.setMobileNo(9089));
}
}
You can create a mapping of the empId to their name using the first list.
Map<Integer, String> empIdToName = employeeNameList.stream()
.collect(Collectors.toMap(Employee::getId, Employee::getName, (a, b) -> a));
Use such a mapping to create the objects further while iterating through the second and looking up this map, such as:
List<Employee> employees = employeeMobileList.stream()
.filter(item -> empIdToName.containsKey(item.getId()))
.map(i -> new Employee(i.getId(), empIdToName.get(i.getId()), i.getMobileNo()))
.collect(Collectors.toList());
//This is my controller
#RequestMapping("/getList")
public ModelAndView getList(#RequestParam(value="page",required=false) Integer page,Model model,#RequestParam(value="page_size",required=false) Integer page_size){
page=0;
page_size=4;
List<Employee> empList = empService.getEmpList1(page,page_size);
Employee emp=new Employee();
model.addAttribute("employee", emp);
return new ModelAndView("empList", "empList", empList);
}
//This is my Sql Query........
select * from EmpDetails LIMIT +page+","+page_size;
//This is my jsp.......for next button.....
Next:
By using this code I am getting the records(0-4) of employee in one page.
My question is when I click on next button the records(4-8) of employees must be displayed in other page. Can you please tell me how to write the code?
Try this code
#RequestMapping("/getList")
public String getList(#RequestParam(value = "page", required = false) Integer page, Model model,
#RequestParam(value = "page_size", required = false) Integer page_size) {
if (page == null) {
page = 0;
}
if (page_size == null) {
page_size = 4;
}
List<Employee> empList = empService.getEmpList1(page, page_size);
Employee emp = new Employee();
model.addAttribute("employee", emp);
model.addAttribute("empList", empList);
model.addAttribute("page", page);
model.addAttribute("page_size", page_size);
return "empList";
}
//This for next button in jsp..... Try and let me know if this link work?
Next:
//This is my Sql Query........
recordStart = page * page_size;
select * from EmpDetails LIMIT +recordStart+","+page_size;
You should not assign strict values to page and page_size variables in your method. Instead of this you should get values from parameters passed to method.
#RequestMapping("/getList")
public ModelAndView getList(#RequestParam(value="page",required=false) Integer page,Model model,#RequestParam(value="page_size",required=false) Integer page_size){
List<Employee> empList = empService.getEmpList1(page,page_size);
Employee emp=new Employee();
model.addAttribute("employee", emp);
return new ModelAndView("empList", "empList", empList);
}
Of course if your page and page_size is optional then you have to check if values are passed. If not then you have to assign some default values.
I want to group some sql data using criteria. Lets start with entity which looks mostly like this:
class CityEntity {
private String name;
private Date lastVisited;
}
What I want to do is to find all cities and return result in a tranformer:
class CityTransformer {
private String name;
private List<Date> lastVisited;
}
So as you can see sql result should group by name and put dates to a list.
I want to do it using criteria so it will look almost like this:
Criteria criteria = session.createCriteria(CityEntity.class, "ce");
criteria.setProjection(Projections.projectionList().add(Projections.groupProperty("name"), "name"));
criteria.setResultTransformer(Transformers.aliasToBean(CityTransformer.class));
List<CityTransformer> cities = criteria.list();
The problem is that I don't know how to aggregate dates (lastVisited) to list. Any help?
For example the input will look like this (name, lastVisited):
[Los Angeles, 10-11-2014],
[Los Angeles, 11-12-2011],
[LosAngeles, 10-01-2011],
[Berlin, 01-10-2011]
and output should look like this
[LosAngeles, list[10-11-2014, 11-12-2011, 10-01-2011]],
[Berlin, list[01-10-2011]]
You don't need SQL grouping for that. You can group it in Java:
Criteria criteria = session.createCriteria(CityEntity.class, "ce");
criteria.setProjection(
Projections.projectionList()
.add( Projections.property("ce.name"), "ceName" )
.add( Projections.property("ce.lastVisited"), "ceLastVisited" )
);
List<Object[]> citiesAndDates = (List<Object[]>) criteria.list();
Map<String, CityTransformer> cityTransformerMap = new HashMap<String, CityTransformer>();
for(Object[] citiesAndDate : citiesAndDates) {
String city = (String) citiesAndDate[0];
Date date = (Date) citiesAndDate[1];
CityTransformer cityTransformer = cityTransformerMap.get(city);
if(cityTransformer == null) {
cityTransformer = new CityTransformer();
cityTransformerMap.put(city, cityTransformer);
}
cityTransformer.getLastVisited().add(date);
}
return cityTransformerMap;
I have the below results as part of resultset.
Name Dept
John IT
Mike IT
Cathy CS
Julie CS
Aria Electronics
Shann Electronics
I should be able to separate the resultset based on Dept and put the results in a map. E.g: After Mike, the dept changes and hence I should put John and Mike in a map. Then Cathy and Julie in a map and so on. How do I do it?
public void loadMap(ResultSet inputResultSet, MbGlobalMap inputTranslationObjMap) throws Exception {
String key = "";
List < dept > list = new ArrayList < dept > ();
while (inputResultSet.next()) {
String name = inputResultSet.getString(1);
String key = inputResultSet.getString(2);
dept d1 = new dept(name, key);
list.add(d1);
}
if (inputTranslationObjMap.containsKey(key)) {
inputTranslationObjMap.update(key, list);
} else {
inputTranslationObjMap.put(key, list);
}
}
Try something like this -
public void loadMap(ResultSet inputResultSet,
MbGlobalMap inputTranslationObjMap) throws Exception {
// String key = "";
List<dept> list = null;
while (inputResultSet.next()) {
String name = inputResultSet.getString(1);
String key = inputResultSet.getString(2);
// first check if the map has a list already.
if (inputTranslationObjMap.containsKey(key)) {
list = inputTranslationObjMap.get(key);
} else {
// No... add a new list to the map.
list = new ArrayList<dept>();
inputTranslationObjMap.put(key, list);
}
dept d1 = new dept(name, key);
list.add(d1);
}
}