I have 3 entities : Country, State, City
I have written their POJOs as :
class Country{
String countryName;
List<State> states;
}
class State{
String stateName;
List<City> cities;
}
class City{
String cityName;
}
My database table is as below :
Goegraphy
---------
countryName | stateName | cityName
Now, for fetching data from database, I made another POJO :
class Geography{
String countryName;
String stateName;
String cityName;
}
I have a List of Geography objects.
But my requirement is to convert this list into the earlier Country-State-City model now. Can someone please help how this can be achieved.
What you are looking for is the One to Many association of relation databases. All JPA implementations can do it nicely for you, without the need of implementing your Geography Pojo.
But if you are stuck to do it manually, here is a not very optimized way of doing it with java 8 streams
class Country {
public Country(String countryName) {
this.countryName = countryName;
this.states = new ArrayList<>();
}
String countryName;
List<State> states;
}
class State {
public State(String stateName) {
this.stateName = stateName;
this.cities = new ArrayList<>();
}
String stateName;
List<City> cities;
}
class City {
public City(String cityName) {
this.cityName = cityName;
}
String cityName;
}
class Geography {
String countryName;
String stateName;
String cityName;
}
List<Country> buildFromGeographies(List<Geography> geos) {
List<Country> result = new ArrayList<>();
for (Geography geo : geos) {
Optional<Country> country1 = result.stream().filter(country -> country.countryName.equals(geo.countryName)).findFirst();
Country country = country1.orElseGet(() -> {
Country newOne = new Country(geo.countryName);
result.add(newOne);
return newOne;
});
Optional<State> state1 = country.states.stream().filter(state -> state.stateName.equals(geo.stateName)).findFirst();
State state = state1.orElseGet(() -> {
State newOne = new State(geo.stateName);
country.states.add(newOne);
return newOne;
});
// taking for granted there is no duplicates in your data set
state.cities.add(new City(geo.cityName));
}
return result;
}
If I understand it correctly you have List from table and you want it to map on you POJO classes. But the problem is that you have duplicated values in table if I understand it correctly. I think you have this data in table
1. USA, Florida, Miami
2. USA, Florida, Sarasota
The Problem will be with dupplication in table. I think you should split each column in separate table and join via foreing key and it will be better. Than you can create select and join to another table and result add to your list. Now you need to create loop.
Related
I am currently learning Java in uni and I encountered this problem:
public class simpleStockManager {
private String sku;
private String name;
private double price;
public void newItem(String sku, String name, double price) {
this.sku = sku;
this.name = name;
this.price = price;
}
public String getItemName(String sku) {
return name;
}
}
I have declared a class and some instance variables and I try to access to items using sku.
So if I declare 3 items in this order:
simpleStockManager sm = new simpleStockManager();
sm.newItem("1234", "Jam", 3.25);
sm.newItem("5678", "Coffee", 4.37);
sm.newItem("ABCD", "Eggs", 3.98);
When I try the getItemName method with sku == "5678" it should return "Coffee", but it's returning "Eggs".
I think it is the latest declared item that overwrites the previous item but I don't know how to solve this.
Any help will be appreciated.
Each call to newItem changes the values of your instance variables.
You will always get the last values set by m.newItem("ABCD", "Eggs", 3.98);
If you wand to use sku as a key to store several variables you can use a Map
For example :
class SimpleStockManager{
// The key of your map will be sku,
//and the name and the price can be for exemple in a Product class
private HashMap<String, Product> products = new HashMap<>();
public void newItem(String sku, String name, double price){
// A call to newItem will create a new Product and store it
products.put(sku, new Product(name, price));
}
public String getItemName(String sku){
if (products.containsKey(sku)){
return products.get(sku).getName();
}else {
return " Product not found...";
}
}
}
I have the following objects in my springboot project.
Student {
private String studentId;
private Date courseStartedDate;
private List<Course> course;
public Date getCourseStartedDate() {
return courseStartedDate;
}
public void setCourseStartedDate(Date courseStartedDate) {
this.courseStartedDate = courseStartedDate;
}
public List<Course> getCourse() {
return course;
}
public void setCourse(List<Course> course) {
this.course = course;
}
}
Course{
private String courseId;
private CourseStatus courseStatus;
public CourseStatus getCourseStatus() {
return courseStatus;
}
public void setCourseStatus(CourseStatus courseStatus) {
this.courseStatus = courseStatus;
}
}
public Enum CourseStatus{
BEGINNER("beginner");
INTERMEDIATE("intermediate");
ADVANCED("advanced");
private String CourseStatus;
CourseStatus(String courseStatus) {
this.courseStatus = courseStatus;
}
public String getCourseStatus() {
return courseStatus;
}
}
I have a list of students which I want to sort in descending order of courseStartedDate and CourseStatus.
I cannot modify the model.
I can sort the list by courseStartedDate as follows:
studentList.sort(Comparator.comparing(Student::getCourseStartedDate).reversed());
I am not sure how to modify the above line of code to sort the list based on CourseStatus as well?
How can I achieve this?
Clarification from comment:
First course in the list of his courses can be considered his primary subject.
Since CourseStatus is an enum (not Enum), it is automatically Comparable, so to add a secondary sort order by status, you call thenComparing():
// ORDER BY courseStartedDate DESC, course[0].courseStatus DESC
studentList.sort(Comparator.comparing(Student::getCourseStartedDate)
.thenComparing(s -> s.getCourse().get(0).getCourseStatus())
.reversed());
Or, if you want to sort the status in ascending order:
// ORDER BY courseStartedDate DESC, course[0].courseStatus ASC
studentList.sort(Comparator.comparing(Student::getCourseStartedDate)
.reversed()
.thenComparing(s -> s.getCourse().get(0).getCourseStatus()));
How to bind from Vaadin RadioButtonGroup country to Country country DAO object? Country is enum and DateField(vaadin) to LocalDate(DAO)
public class Person {
#Id
String id;
LocalDate dateBorn;
Country country;
......
public class PersonFormUI extends GridLayout {
RadioButtonGroup<Country> country;
DateField dateBorn;
........
public enum Country {
EN, DE, IT }
with this binding all fields are binded and runs well but how to bind enums and dates withConverter?
binder.bindInstanceFields(this);
binder.setBean(personDAO);
If I may add a couple of suggestions before going straight to code:
If you want a nicely aligned form you can use FormLayout
I'd suggest using a ComboBox instead of RadioButtonGroup to display the countries, as it uses less space and also allows you to quickly find what you want by typing in it. But if you really want the radio, replace the combo line with RadioButtonGroup<Country> countries = new RadioButtonGroup<>("Country", DataProvider.ofItems(Country.values()));
You can find below a sample of binding based on the suggestions above and Vaadin 8.3.1. I don't see the need for any conversions, since the framework will take care of it for you.
The only extra thing I did, was to add an ItemCaptionGenerator for the combo to display the full country name instead of the default, which uses the Enum name (same thing can be used with RadioButtonGroup).
Code:
public class PersonForm extends FormLayout {
public PersonForm() {
// form components
DateField birthDate = new DateField("Birth date");
ComboBox<Country> countries = new ComboBox<>("Country", Arrays.asList(Country.values()));
// use full country name instead of ugly Enum name
countries.setItemCaptionGenerator(Country::getFullName);
// do not allow the user to select "nothing"
countries.setEmptySelectionAllowed(false);
// binder setup
Binder<Person> userBinder = new Binder<>();
// birth date binding
userBinder.forField(birthDate)
.asRequired("Please provide a birth date")
.bind(Person::getDateBorn, Person::setDateBorn);
// country binding
userBinder.forField(countries)
.asRequired("Please select the country of residence")
.bind(Person::getCountry, Person::setCountry);
// bind to bean with some existing value (eg, loaded from DB for editing)
userBinder.setBean(new Person(LocalDate.now(), Country.RO));
// simulate a save action
Button saveButton = new Button("Save", event -> Notification.show("Saved new user info: " + userBinder.getBean()));
// add fields to the UI
addComponents(birthDate, countries, saveButton);
}
// beans
public class Person {
private LocalDate dateBorn;
private Country country;
public Person(LocalDate dateBorn, Country country) {
this.dateBorn = dateBorn;
this.country = country;
}
public LocalDate getDateBorn() {
return dateBorn;
}
public void setDateBorn(LocalDate dateBorn) {
this.dateBorn = dateBorn;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
#Override
public String toString() {
return "Person{" +
"dateBorn=" + dateBorn +
", country=" + country +
'}';
}
}
public enum Country {
RO("Romania"), DE("Deutschland"), IT("Italy");
private String fullName;
Country(String fullName) {
this.fullName = fullName;
}
public String getFullName() {
return fullName;
}
}
}
Result:
You can go even further and disable the button based on the binder status (maybe you want to use the same form to add new people where there are no initial values):
// disable saving until all required data is available
userBinder.addStatusChangeListener(event -> saveButton.setEnabled(userBinder.isValid()));`
Result:
I am writing a JSP webapp and right now I'm kind of stuck. I have been using an ArrayList of Java Objects, each with a list of properties. They are Order objects with properties like firstName, lastName, etc. At this point in my development I need to store the individual orders as JSON arrays in javascript variables. I am able using a servlet to convert the arraylist to JSON but the JSON has repeat properties for each of the Order objects, like this:
[{firstName : Mike, lastName : Daniels, ..... firstName : John, lastName : Doe ... etc ...}]
Clearly, the JSON is made up of all of my Order objects, strung together as one JSON array. What I am wondering is how I need to split up the string into separate variables depending on the number of Orders in the app at the time.
Here's how the object is set if it helps. Thanks!
Object orders = request.getSession().getAttribute("orders");
//this is a string of order properies/values
String json = new Gson().toJson(orders);
HttpSession session = request.getSession();
session.setAttribute("jsonOrders", json);
Try iterating through the array list, creating a JSON object for each of the objects instead of converting the array list as a whole.
Let's suppose your orders entity is something like this:
public class Order {
private String firstName;
private String lastName;
// getters & setters
}
and you get your orders data in request like:
[{
"firstName": "Mike",
"lastName": "Daniels"
}, {
"firstName": "John",
"lastName": "Doe"
}]
You should be able to convert it to List<Order> using
List<Order> orders = gson.fromJson(response, Order.class);
You can then iterate over the list like:
for (Order order: orders) {
// Whatever you want to do
}
Or, if you are using java 8:
orders.forEach (order -> System.out::println);
Here is the solution using Gson library,
//Order.java
public class Order {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
//Orders.java
public class Orders {
Order[] order;
public Order[] getOrder() {
return order;
}
public void setOrder(Order[] order) {
this.order = order;
}
}
import com.google.gson.Gson;
//Solution.java
public class Solution {
public static void main(String[] args) {
String json = "{\"order\":[{\"firstName\":\"Mike\",\"lastName\":\"Daniels\"},{\"firstName\":\"John\",\"lastName\":\"Doe\"}]}";
Orders orders = new Gson().fromJson(json, Orders.class);
Order[] orderArr = orders.getOrder();
for(int i=0; i<orderArr.length;i++){
System.out.println("First Name : "+ orderArr[i].getFirstName());
System.out.println("Last Name "+orderArr[i].getLastName());
}
}
}
**Output**
First Name : Mike
Last Name Daniels
First Name : John
Last Name Doe
Answer by ssc looks right. Best way to do is iterate through the list.
Is there any way to project multiple values for an root entity object using Criteria?
Assume we have these classes (With the proper mappings):
class Boss {
private String name;
private List<Employee> employees;
// setters and getters and more stuff
}
class Employee {
private String name;
// setters and getters and more stuff
}
Then i am trying to do this :
public void test() {
Criteria criteria = this.getSession().createCriteria(Boss.class);
criteria.createAlias("employees","employees");
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.property("name"), "name");
projectionList.add(Projections.property("employees.name"), "subordinatesNames");
criteria.setProjection(projectionList);
criteria.setResultTransformer(new AliasToBeanResultTransformer(BossBean.class));
List<BossBean> results = criteria.list(); // fails here
for (BossBean bossBean : results) {
System.out.println (bossBean);
}
}
This is how the Bean looks like (nothign special, just for grouping values) :
public static class BossBean {
private String name;
private List<Strings> subordinatesNames;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Strings> getSubordinatesNames() {
return subordinatesNames;
}
public void setSubordinatesNames(List<Strings> subordinatesNames) {
this.subordinatesNames = subordinatesNames;
}
}
The exception is this :
2014-06-06 13:37:38 [main] ERROR org.hibernate.property.BasicPropertyAccessor - expected type: java.util.List, actual value: java.lang.String.
I Guess is trying to fit the String returned from Boss(root object) -> (A)Employee(association) ->name(value) into a List.
I want to auto magically get all inserted in the List. Is there a way to achieve this using Criteria? If not, how i can achieve it?
Thanks in advance!
Grettings
VĂctor