How to save a mapping of similar data in DB using JPA - java

I don't know how to design this rdbms problem:
Let's say, I have a customer, who is making a purchase. By making the purchase he leaves his data. I have a second dataset with real customer data. After collecting the data, I want to find a mapping of the collected customer data to the real customers by an algorithm.
It's still unclear how to save this mapping/these links created by the algorithm.
Proposal:
#Entity
public class Purchase{
#OneToOne
private Customerdata customerData;
}
#Entity
public class CustomerData{
private String firstName;
private String Lastname;
private String city;
}
#Entity
public class RealCustomer{
#OneToMany(cascade=CascadeType.ALL, mappedBy ="RealCustomer")
private List<CustomerData> customerData = new ArrayList<CustomerData>();
private String firstName;
private String Lastname;
private String city;
}
Now I can save my assumed mapping from RealCustomer data to customer data in the customerData list.
I guess that's not the best idea?
Hoping for nice suggestions from you. Can I take advantage of the similarity of real customer data and obtainer customer data.
Please note that I want to keep inconsistent data e.g. even if city is similar ('Washington D.C.' and 'Washington'. I don't want to lose this information that I can run the matching algorithm later again.
Note: I'm okay, if you provide me the rough idea. Java/JPA-Code not necessary.
Thank you very much in advance!

You can do something like below
#Entity
public class Purchase{
#OneToOne
private Customer customer;
}
#Entity
public class Customer{
private String firstName;
private String Lastname;
private String city;
//Below association will only come in picture if customer has real customer data available when you are collecting the data this way you can clearly identify and separate collected vs real customers
#OneToOne
Customer realCustomer;
}

Related

How to select only certain fields with Quarkus Panache?

Quarkus simplifies Hibernate ORM mappings with Panache.
Here is an example of my entity and PanacheRepository:
#Entity
public class Person {
#Id #GeneratedValue private Long id;
private String firstName;
private String lastName;
private LocalDate birth;
private Status status;
}
#ApplicationScoped
public class PersonRepository implements PanacheRepository<Person> {
// example
public Person findByName(String name){
return find("name", name).firstResult();
}
// ! and this is what I tried, but it's not possible to do it this way
// all the methods return Person or something of type Person like List<Person>
// so basically this won't even compile
public List<String> findAllLastNames() {
return this.find("select p.lastName from Person p").list();
}
}
All the guides explain how to write different queries, but is not clear how to select only certain attributes.
If I don't need the whole Person object, but rather the lastName of all persons in my DB?
Is it possible to select only certain attributes with Quarkus Panache?
This is currently not possible, you can subscribe to this issue regarding projection for Hibernate with Panache: https://github.com/quarkusio/quarkus/issues/6261
Don't hesistate to vote for it (+1 reaction) and provides feedback.
As #aksappy said, this feature was added and it's documentation is available here.

List denormalization with morphia

Suppose i have two morphia entities: Person and Team which are look like this
#Entity
public class Person {
private String name;
private String login;
private String mail;
private List<Team> teams;
}
#Entity
public class Team {
private String name;
private String description;
private List<Person> members;
//some more fields
}
I want map this model into Mongodb database like this
Users collection
{
name:"someName",
login:"somelogin",
mail:"some#mail.com",
teams: [
{id:"teamId", name:"TeamName"} //only specific fields fron Team Entity
{id:"anotherTeamId", name:"AnotherTeamName"}
]
}
Teams collection
{
id:"teamId",
name:"TeamName",
description:"Very strong team",
members: [id:"aaa", name: "someName"] //only specific fields fron User Entity
//some other fields
}
{
id:"anotherTeamId",
name:"AnotherTeamName",
description:"Brave new team",
members: [id:"aaa", name: "someName"] //only specific fields fron User Entity
//some other fields
}
So, I want denormolize only specific fields (only name for example) from Team document into User's teams field.
I don't understand Can I use morphia (or some other odm) for this case? Which annotations I should use in my Entities?
It seems that #Reference annotation is not allowed with List<> fields.
I think, i should create inner class PersonTeam, which will contain Team's name and id, and use it in Person class
#Entity
public class Person {
private String name;
private String login;
private String mail;
private List<PersonTeam> teams;
}
public class PersonTeam {
private String teamId;
private String teamName;
}
Is this a good way to solve my problem? thank you!
That's about the only way to do it with morphia at least. You might consider using #Reference on those fields and only storing the IDs. That'd help if your concern is saving space.

hibernet one to many on web

I am completely new in Hibernate ORM world, recently reading mapping specially one-to-many relation. But i am facing some problem to understand.
I am using this link to understand hibernate relation.
https://dzone.com/tutorials/java/hibernate/hibernate-example/hibernate-mapping-one-to-many-using-annotations-1.html
please have a look the code.
public class Student {
private long studentId;
private String studentName;
private Set<Phone> studentPhoneNumbers
//setter getter
}
public class Phone {
private long phoneId;
private String phoneType;
private String phoneNumber;
//setter getter
}
i understand it.
confusion is here.
Set<Phone> phoneNumbers = new HashSet<Phone>();
phoneNumbers.add(new Phone("house","32354353"));
phoneNumbers.add(new Phone("mobile","9889343423"));
Student student = new Student("Eswar", phoneNumbers);
session.save(student);
Does this only one code session.save(student), store value in both table ? if no then why we didn't write code to save phoneNumbers like session.save(phoneNumbers).
Once this above code is executed then the value will be stored in both table or object(STUDENT and PHONE) right ?. I think each time we execute this code, this code insert value in both table. i don't like it. i want value should be store on only second table(PHONE).
So how will i store value in only PHONE object ?
or how will we implement this relation where user will select STUDENT through combobox and fill value in PHONE object through simple textboxes. then finally save it.like product/category.
3.please help or suggest some good tutorial where hibernate is implemented (specially one-to-many and many to many relation) in web application. i have seen many tutorial but all these are implemented through main method.
sorry for the poor English
thanks.
Yes it should save both student and phone number in their own table. If you annotate the right way. Student should be something like this:
#Entity
#Table(name = "student")
public class Student {
#id
#GeneratedValue
private long studentId;
#column(name = "studentName")
private String studentName;
#OneToMany
private Set<Phone> studentPhoneNumbers
//setter getter
}
public class Phone {
private long phoneId;
private String phoneType;
private String phoneNumber;
//setter getter
}
Then there is also some configuration to do. I'd advice you to read this tutorial: https://www.tutorialspoint.com/hibernate/index.htm
In the case of your code it doesn't much. But if you configure hibernate the right way you can decide in which table/column a value should be saved
Hibernate tutorial - Tutorials point

Java Domain Design

I've been going back and forth on the best way to design and implement a domain layer in Java while using the SpringJDBC Template. I want to design something that is going to be reusable and robust, while avoiding the n+1 query problems and performance problems. I've come up with a couple cases but not sure which one would be best for use with JDBC. I've used Hibernate previously. What is the best way to approach domain design in Java assuming SpringJDBC will be the technology interacting with the database.
As an example lets say I have an Address, which has a State, which has a Country.
Case 1: Domain object exact match to database
public class Address {
private long id;
private String streetLine1;
private String streetLine2;
private String city
private long stateId;
private String zipCode;
...
}
public class State {
private long id;
private String name;
private String code;
private long countryId;
}
public class Country {
private long id;
private String name;
private String code;
}
In this case the domain objects are an exact representation of a database tables, thus row mapping is simple, and the objects can be persisted into the database.
The major downside I can see to this is, lets say on the user interface I need to list all addresses in the application, and the want Street 1, Street 2, City, State (full name), Postal Code, and Country. If there are 100 address that are returned, I then need to issue two additional queries per row to get the State object, and Country object for a ground total of 201 queries executed, OUCH!
Case 2:
Follow the same design as Case 1, but when you encounter a situation where the UI requires components from multiple domain objects, return a custom DTO object by having the RowMapper map to the DTO object instead of the domain, makes it possible to execute one query. The downside I see here is you may end up with a ton of special case DTO / Model objects.
public class AddressDTO {
private long id;
private String streetLine1;
private String streetLine2;
private String city;
private String state;
private String country;
}
Case 3:
Map similar to how you would in hibernate where domain objects reference each other. However now the RowMappers get more complex, and they may be fetching data unnecessarily. At that point it is expected that the objects would always be populated, since there is no lazy loading like what JPA/Hibernate can do. In order to persist and Address, the Address object would need a valid State object associated. This seems like the least practical solution but I maybe there is something I'm not understanding.
public class Address {
private long id;
private String streetLine1;
private String streetLine2;
private String city
private State state;
private String zipCode;
...
}
public class State {
private long id;
private String name;
private String code;
private County country;
}
public class Country {
private long id;
private String name;
private String code;
private Set<State> states;
}
I would go with Case 2 because when you need to query across domains it makes more sense to use usecase driven DTOs and use SQL Join(s) to get data from the linked domains

Morphia: can two objects pull from the same collection if one is a subset of the other?

Lets say I have two very basic classes that share most of their information that I want to store in mongo. Like this:
public class Customer{
#id
private int customerID;
private String Name;
private int social;
private long balance;
}
public class CustomerInfo{
#id
private int customerID;
private String Name;
private int social;
private long balance;
private Address address;
private PhoneNumber phoneNumber;
}
If I don't want to have two nearly-identical collections when one should do. Can I create a single collection for CustomerInfo and still populate the Customer class with the records contained inside, since they are a subset of CustomerInfo?
I know I can load customerInfo with only the values I care about, but I would like something that is a little more elegant, and which plugs into my existing format better.
#Entity(value="customers", noClassnameStored=false)
public class Customer {
#Id
private ObjectId id;
private String Name;
private int social;
private long balance;
}
public class CustomerInfo extends Customer {
private Address address;
private PhoneNumber phoneNumber;
}
It should work like that. Since you are storing the class name in each document, you can easily query for the one you want to use; even though Morphia would figure this out on its own based on the attributes.
PS: And unless you know what and why you are doing it, keep your ID an ObjectId.
PPS: You might want to use object data types instead of primitives in case they can be empty — in which case they won't be stored and use up space in in your database.

Categories

Resources