hibernet one to many on web - java

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

Related

How to do one to many relationships in JDBC?

I have class two classes
i want to perform one to many relationship
public class Teacher {
private int id;
private String name;
private List<Class> classes;
}
public class Class {
private int id;
private String className;
}
I need to retrieve data and print data from the database
Teacher Classes
Kumar A1,B3,B4
Deepa A1,A2,C1
Alex B2,D1,D2
I don't Know how to retrive one to many relationship data in JDBC
please suggest me what should i do?
I do know about 2 ways to do it with jdbc
You need to select all teachers first, then for each teacher select his classes.
select * from teacher
then map results to your teacher class then on java side make a for each loop and fetch class by teacher_id for each teacher
select * from class where teacher_id = :teacher_id
You can select all teachers and classes like that:
select * from teacher t
left join class c on c.teacher_id = t.teacher_id
but you will get duplicate data of teacher becouse in each row you will fetch data for teacher also and you will need to organize it on Java side.
So I've been working recently with Spring JDBC myself. This is something similar with what I've come up with by reading here and there. I really appreciate the simplicity of JDBC combined with the domain driven approach:
public class Teacher {
#Id private int id;
private String name;
#MappedCollection(idColumn = "teacher_id", keyColumn = "teacher_key")
private List<Class> classes;
//setters and getters
}
public class Class {
private int id;
private String className;
//setters and getters
}
Then you need to create the repository interface by extending CrudRepository from Spring JDBC, you don't need to create an extra repository to e.g. save Class data through Teacher :
interface TeacherRepository extends CrudRepository<Teacher, Integer> {}
The TeacherRepository will have the typical CRUD methods that allow you to read or write data from/to the database.
The sql code (this is postgres like, change to your specific dialect) would be something like this:
create table teachers(
id serial primary key,
name text
)
create table classes(
id serial primary key,
class_name text,
teacher_id int references teachers(id),
teacher_key int
)
Where the teacher_key column is used to return an ordered list of classes. If you don't care about the classes ordering you can just return a set instead of a list:
public class Teacher {
#Id private int id;
private String name;
#MappedCollection(idColumn = "teacher_id")
private Set<Class> classes;
//setters and getters
}
public class Class {
private int id;
private String className;
//setters and getters
}
the sql code:
create table teachers(
id serial primary key,
name text
)
create table classes(
id serial primary key,
class_name text,
teacher_id int references teachers(id)
)
Here are my sources:
https://www.youtube.com/watch?v=ccxBXDAPdmo
https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates
https://lumberjackdev.com/spring-data-jdbc
https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#jdbc.repositories

How to retrieve multiple entries from table into one list?

thanks for helping ;)
I'm new to hibernate and wanna try it for my private project.
What i want to do is: I want to have a class like
public class Playlist {
private long id;
private String name;
private long owner_ID;
private ArrayList<String> urls;
}
Where the list should contain urls to some songs.
At the moment I have one entry in my db for each url. Is there a better way to do that?
And to my main question: How can I recieve/save the list?
I can get a "normal" table entry rn but I haven't worked with Hibernate and Lists/ArrayLists in combination jet.
Hope you can help me ;)
If additional information is required feel free to ask.
Since the urls is a basic value (String) you can use #ElementCollection.
#Entity
public class Playlist {
#Id
private Long id;
private String name;
private long owner_ID;
#ElementCollection
private List<String> urls;
}
This mapping links two tables:
playlist table which has id, name, owner_ID columns
playlist_urls table which has playlist_id and urls columns.
For more information take a look at here.

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.

How exactly does the Hibernate #OneToMany annotation work?

I am pretty new to Hibernate and I am studying it on a tutorial. I have some problems understanding how exactly the OneToMany annotation works.
So I have these 2 entity classes: Student that represents a student and Guide that represents a person that guides the student. So each student is associated with a single guide but a single guide can follow more that one student. I want a guide to know the students associated to him.
So I have:
Student:
#Entity
public class Student {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name="enrollment_id", nullable=false)
private String enrollmentId;
private String name;
#ManyToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
#JoinColumn(name="guide_id")
private Guide guide;
public Student() {}
public Student(String enrollmentId, String name, Guide guide) {
this.enrollmentId = enrollmentId;
this.name = name;
this.guide = guide;
}
public Guide getGuide() {
return guide;
}
public void setGuide(Guide guide) {
this.guide = guide;
}
}
So the #ManyToOne annotation on the guide field:
#ManyToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
#JoinColumn(name="guide_id")
private Guide guide;
means that a single guide is associated a single student but a guide can follow many students. Is it right? What exactly does the specified cascade settings do? I think it means that when I persist a Student object that contains a Guide object as field also this Guide object is also automatically persisted. And the same thing happens when I remove a Student object, the related Guide record is deleted...but I am not absolutely sure about it...
Ok, doing it this way I will have a mono directional relationship between a record in the Student table and a record in the Guide table because in the Student table I will have a foreign key to join the Guide table so the student can know its guide but, doing it this way, the guide can not know the followed student...and this is not smart.
To do it the Guide class is implemented in this way:
#Entity
public class Guide {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name="staff_id", nullable=false)
private String staffId;
private String name;
private Integer salary;
#OneToMany(mappedBy="guide", cascade={CascadeType.PERSIST})
private Set<Student> students = new HashSet<Student>();
public Guide() {}
public Guide(String staffId, String name, Integer salary) {
this.staffId = staffId;
this.name = name;
this.salary = salary;
}
public Set<Student> getStudents() {
return students;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
public void addStudent(Student student) {
students.add(student);
student.setGuide(this);
}
}
So, as you can see, this class contains:
#OneToMany(mappedBy="guide", cascade={CascadeType.PERSIST})
private Set<Student> students = new HashSet<Student>();
that it is used to declare the bidirectional relationship.
So it seems to me that this annotation automatically create a guide_id field into the Student table that represent the foreign key that implement the bidirectional relation.
In fact using this mapping the Student table is automatically created in this way in my database:
'id', 'bigint(20)', 'NO', 'PRI', NULL, 'auto_increment'
'enrollment_id', 'varchar(255)', 'NO', '', NULL, ''
'name', 'varchar(255)', 'YES', '', NULL, ''
'guide_id', 'bigint(20)', 'YES', 'MUL', NULL, ''
So in the Student entity class I have not defined the guide_id field but I have it in the Student table on the database. So I think that the creation of this field in the table depends on the previous #OneToMany annotation defined in the Guide entity class. Is that correct or am I missing something?
Yes, you can define a #OneToMany entity without a bidirectional association, and the added column is on the Many entity side in the database (even though the entity doesn't know it is linked to the One-side entity).
You can also use a join table for this, but it's not necessary.

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

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;
}

Categories

Resources