I have POJO classes:
class Ticket {
private int id;
private double cost;
private Date time;
private List<Place> places;
// Getters and setters here
}
class Place {
private int row;
private int place;
// Getters and setters here
}
Then I create one ticket and some places:
Ticket ticket = new Ticket();
ticket.setCost(58.7);
ticket.setTime(new Date());
Place place1 = new Place();
place1.setRow(1);
place1.setPlace(2);
ticket.addPlace(place1);
Place place2 = new Place();
place2.setRow(3);
place2.setPlace(4);
ticket.addPlace(place2);
And now I want to save it to DB:
session.insert("insertTicket", ticket);
session.commit();
In MapperConfig.xml I write this lines:
<insert id="insertTicket" parameterType="Ticket">
INSERT INTO tickets (cost, time) VALUES (#{cost}, #{time})
</insert>
How I can save List places in automatic mode?
Does MyBatis can save it for me?
Or I need to iterate manually with foreach and insert every Place by hand?
Thanks for any help.
Even though MyBatis is able to support the reverse direction (i.e. filling the list during a query with a nested select or from a join), there is no automatic mode that inserts the containing list into the database.
According to this Google Groups discussion you have to insert the list elements manually.
Related
I have a List result in my Spring Boot service method as shown below:
Country:
String name;
List<State> states;
State:
String name;
Long population;
List<Town> towns;
Town:
String name;
I return Country list from my repository and it has all the related State and Town date for each Country. I want to map this data to a DTO as shown below:
public class CountryDTO {
private Long id;
private String name;
private Long population; //population sum of states by country
private List<Town> towns;
//constructor
}
So, how can I map my Country entity to this CountryDTO properly as explained above? I need the following data:
Country name
Sum of population by each country
Towns of each country
Update: Here is my service method where I tried to use Java Stream and then also ModelMapper, but cannot return desired values :(
List<CountryDTO> countries = countryRepository.findAll().stream()
.flatMap(x -> x.getStates().stream())
.map(x -> new CountryDTO(x.getCountry(), <-- need to return sum of population here -->, ObjectMapperUtils.mapAll(x.getTowns(), TownDTO.class)))
.toList();
You can use Stream#mapToInt to get all the state populations and .sum to add them up.
Stream#flatMap can be used to get all the towns of each state into a single stream.
List<CountryDTO> res = countries.stream().map(c -> new CountryDTO(c.getName(),
c.getStates().stream().mapToInt(State::getPopulation).sum(),
c.getStates().stream().flatMap(s -> s.getTowns().stream()).toList())).toList();
Didn't get your question completely, maybe it will be more helpful if you share the exact response returned by the APIs.
But, going by the use case, if you are getting a list in the response, you always have the option of stream the list, iterate each element, and then use conditional / grouping logics to get the data in the desired way.
For example;
Let's say, you have a list of Object type, for which you have a repository layer configured as ObjetRepo. Now, if you are getting a list of objects, you can stream it like this:
#Autowired
private ObjectRepo objectRepo;
public List<Object> method() {
List<Object> objects = new ArrayList<>();
objectRepo.findAll().forEach(objects::add);
// Here, instead of add, any other logic can be used.
// You can also write a method, and use that method here
// objectRepo.findAll().forEach(objects::someMethod);
return objects;
}
Hope this helps.
I have two different csv files having data on two different entities and I have to merge two different csv files to create one on the basis of sql join type equijoin and left join.
so I have created first entity as class name Customer having attributes:
int CustomerId ;
String CustomerName;
int OrderId;
And List of object of this class like:
Customer c1 = new Customer(CustomerId, CustomerName, OrderId);
1 million objects..
List<Customer> cust = new ArrayList<>();
cust.add(c1);
cust.add(c2);
so on to make list of 1 million object.
Similarly, I have created class of second entity Order having attributes:
int orderId;
String orderName;
Date orderdate;
Order o1 = new Order(orderId, orderName, orderdate);
so on 1 million object
List<Oder> order = new ArrayList<>();
Now I need to merge both the object on the basis of orderId and generate third object having result class having all the attributes from both the classes described above.
Please suggest me solution using java stream 8 to map both the streams of list to create inner join and left join type example in the third new result class.
Aside from the getters, your Customer class should have the following method:
public boolean orderMatch(Order order) {
//fixed the attribute name so it would be in camelCase
return orderId == order.getId();
}
Of course, this implies that Order has a getId() getter method to get its id attribute.
Finally, you'll need a CustomerExtended class.
class CustomerExtended {
int customerId ;
String customerName;
Order customerOrder;
public CustomerExtended(Customer customer, Order order) {
customerId = customer.getId();
customerName = customer.getName();
customerOrder = order;
}
}
Now, you can create a Function which would search for the corresponding Order and append it to a Customer:
Function<Customer,CustomerExtended> extendCustomer = (c) ->{
//I used the more descriptive name orderList instead of o1.
Optional<Order> order = orderList.stream()
.filter(c::orderMatch)
.findFirst();
if(order.isPresent()) {
return new CustomerExtended(c,order.get());
}
return null;
};
And then you can apply it to the Customer list through a map.
List<CustomerExtended> newCustomerList = customerList.stream()
.map(c -> extendCustomer.apply(c))
.collect(Collectors.toList());
EDIT: A few last notes
There should be some check that the ID numbers are not duplicate either when adding the objects to the lists, or when the lists are populated.
For semantic purposes, The Customer object as it is should be renamed CustomerOrder or be separated into an object only for customer info and an object which would store the relation between customer and order.
The case where an order is not found should be better handled and throw an exception.
Im wondering the best way of storing the following information:
I have an Account Object, within each account object I need to keep track of date, items purchased on that date, and the number of items . This is in addition to many other things such as client ID for the account. Im about to implement this in the following way
class Account{
int clientID;
LinkedHashMap<String(the date), Map<int(itemID), int(quantity)>> = new ...
...
}
I was wondering if anyone has any time before I go ahead and implement this? I mean other thing I thought of was an inner class such as
Class Account{
class Item{
String Date
Array<Int> itemID
Array<Int> item quantity
}
But I feel the first way wold be better. THanks for your suggestions.
P.S I know there's issues in the code like the brackets in the hashmap this is just to help you see what I'm getting at :)
I think this could be good design:
public class Acount {
private int clientId;
private List<Purchase> purchases;
}
public class Purchase {
private Date date;
private Map<Item, Integer> itemsCount;
}
public class Item {
private int itemId;
}
An Account has a clientId and a list of purchases.
Each Purchase has a date and a map that identifies the purchased Items and the quantity of each one.
Best way to store id and data
HashMap<String, String> multiMap = new HashMap<String,String>();
// Put elements to the hashMap
hashMap.put("id1", "data1");
hashMap.put("id2", "data2"); hashMap.put("id3", "data3");
i am trying to retrieve records from the db for three different columns. I need a way to store the data from these columns so that i am able to iterate through the first column and put some checks on the data from the other two columns. the first thing i was trying was to have three different list and each list having records from those three columns simultaneously but that way i wont be able to return all the three lists from a single method, I need all those data retrieved from the db and then i am gona use it in another class. Is there a way a list can have more than one lists inside of it. Is there any other solution for this problem, an other suggestions.
thanks.
Create a bean (Say DbResult) with three fields column1, column2 and column3.
Then create and return a list of DbResult: List<DbResult> resultList = new ArrayList<DbResult>();
This way you can pass all your data to the caller method;
Review DTO patern DTO
In java you would declare a class with three fields. For example like this:
public class Person {
public String firstName;
public String lastName;
public String birthName;
}
(if you prefer, you can also use getter and setter methods)
You can then store instances of that class in a list:
List<Person> persons = new ArrayList<>();
Person person = new Person()
person.firstName = "Mario"
...
persons.add(person);
If you are not allowed to create new Java-files (for whatever reason...), than you can even include the Person class inside of another class or interface:
public class ExistingClass {
public static class Person {
...
}
...the rest of the the existing class...
}
You should create a class which ll hold a row's data from the tabel.
Like :
Class Row {
int column1;
int column2;
int column3;
}
And then you should create a list of this class objects like : List<Row>.
In this way you can iterate through one list and access all column values and you can also return the list in any function.
I have an object product in my application. This object has a list of items inside it (ArrayList). In the database I have 2 tables: Product and Item. Items have ids of products connected with foreign keys to product id.
It is quite simple to get the Product from database and then get a list of items for it.
How to get a list of products from the database, which will contain all the relevant items inside?
As far as I know, it is not efficient to call dao for every product in the list. How can I manage the query, or object creation to make it more efficient?
I am using Spring JdbcTemplate to get data from Database. Currently I am getting list of products in DAO class and straight from there I call ItemDAO for every item. The database is MySQL.
Update
Okay, probably I was unclear in my first approach. The goal is to get nested lists from Database and how to make it performance-wise.
public class Product {
private Integer id;
private String name;
private String description;
private ArrayList<Item> items;
private Timestamp timeAdded;
}
public class Item {
private String name;
private Float price;
private String type;
private Integer productId;
}
public ArrayList getProducts(String searchName) throws SQLException {
ArrayList<Product> products = new ArrayList<Product>();
String sql = "SELECT * FROM product WHERE name LIKE '%" + searchName + "%'";
List<Map> rows = getJdbcTemplate().queryForList(sql);
for (Map row : rows) {
Product product = setNewProduct(row);
products.add(product);
}
return products;
}
private Product setNewProduct(Map row) {
Product product = new Product();
product.setId((Integer) row.get("id"));
product.setName((String) row.get("name"));
product.setDescription((String) row.get("description"));
ItemsDao itemsDao = (ItemsDao) appContext.getBean("itemsDao");
ArrayList<Item> items = itemsDao.getItems(product.getId());
if (items.size() > 0) {
product.setItems(items);
}
product.setTimeAdded(new java.util.Date(((Timestamp) row.get("time_added")).getTime()));
}
In ItemsDao class I just get a list of items for the product, based on the ID sent.
So the question is how to call list of products and get list of items inside every product? (maybe in one complex SQL statement?). Now the performance is horrible, because when there are 30 products with 10 items each, to get the whole list of products it will have to call database so many times.
The answer is that you can't when using an ORM, they all perform like crap when you have any amount of data. OK if you lazy-load the related collections and only use a few, but if you need to display field from the child objects then you can get 100,000+ queries for a page load. Believe me I just ahd to optimise a page using Doctrine that ran 200,000 queries.
What you have to do is either to paginate the results, or to write a custom query that joins the data and then process the results with a loop control: eg
$sql = "SELECT * FROM table1 t1 JOIN table2 t2 ON t1.id = t2.fk_id";
// run query and get resdults
$cur_prod = '';
While( // fetch a row ){
if($row['prod'] != $cur_prod){
$cur_prod = $row['prod'];
// start the new record in your layout
}
echo $row['t1.f1'];
echo // blah blah blah the related data
}
What I am getting at here is that you have to track the parent product and manage the output when it changes.