Is it possible to use one-to-many and many-to-one in the same entity? - spring

I would like to modify the spring's rest tutorial. Link here
The tutorial has two entity: User and bookmark ( many bookmark can belong to one user. )
I would like to modify it a bit. I would like to create a user, question, answer entity - a user can have many questions, and a question can have many answers.
Is this possible?
How should the entity definition look like for the question entity?
The logic would be that a user could create quizzes. The quiz can contain questions, and those questions may have possible answers.
Any ideas how should the entities look like?
I would appreciate every idea.

Is it possible to use one-to-many and many-to-one in the same entity?
I assume your question is, can "questions entity" have one-to-many relationship with Answers entity and many-to-one relationship with User entity at the same time.
Yes, it is possible. Just, be careful while using annotation to map your entities each other, otherwise performance of your application will be seriously degraded. Use eager/Lazy fetch wisely. Print out the sql queries that spring-data-jpa/hibernate fires under the hood and analyze.

It is definitely possible.
User
#Entity
public class User {
// id and other attributes ommited
// User and Quiz has OneToMany bidirectional relationship. OP hasn't specified that but I think it makes more sense because a quiz most likely will need to know the user who created it.
#OneToMany (mappedBy="user", cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
private List<Quiz> quizes;
// ...
}
Quiz
#Entity
public class Quiz {
// id ommitted
#OneToMany
private List<Question> questions;
#ManyToOne
#JoinColumn(name = "user_id") //quiz table will have a column `user_id` foreign key referring to user table's `id` column
private User user;
// ...
}
Question
#Entity
public class Question {
// id ommitted
#OneToMany
#JoinColumn(name="question_id") // Question and Answer has one-to-many unidirectional relationship. `answer` table has a foreign key `question_id` referring to `question.id` column
private List<Answer> answers;
// ...
}
Answer
#Entity
public class Answer {
// ..more attributes
}
Note that:
the entity relationships also depend on your business logic.
If the owner of the bidirectional relationship is different, then your client code needs to adjust. jpa-joincolumn-vs-mappedby
If you want to design your table to be "clean" such that one entity table does not have a foreign key referring to another associated entity. You can create a join table, make the OneToMany relationship "feel" like a ManyToMany and use unique index to enforce the OneToMany. It is up to you. This wikibook page explains pretty well
This is absolutely not the only solution.

Related

How to obtain the bi-directional entity

Let's say we have two entities, EntityA and EntityB, and those entities are bidirectional. How we should obtain entityB? Does it make sense to add a new method to the repository like findAllByEntityA() or we may use getEntitiesA() getter?
You could add a new spring repo method, or simply use a #Getter annotation, or implement your own getter method.
You could do findAllByEntityA() as a way of fetching EntityB if you expect to have a List<EntityB> returned. On the other hand, I would expect based on the naming convention that getEntitiesA() would be for fetching a List<EntityA> & not for B's.
It really depends on your bi-directional relationship but, basically all of the jpa one-to-one, one-to-many, many-to-one, many-to-many mappings simply boil down to foreign key constraints.
as turbofood already said. There are differet kinds of mappings:
One-to-One mappings. Like a Driver and a Car: One car can only be driven by one Driver and one Driver can only drive one Car.
Many-To-One mappings: Like a father and a child, one Father can have multiple children but one children can only have one father.
Many-To-Many mappings: Like student and teacher. A student can have multiple teachers and one teacher can have multiple students.
For One-To-One-Mappings and for Many-To-One mappings you have exactly one foreign-key. But for Many-To-Many-Mappings you have two foreign-keys that are part of a db-relation-table (that must not have a jpa-entity).
Using JPA/Hibernate we differenciate the endpoints between relations into two kinds: The owning-Side (getter and setter) and the non-owning side (getter and setter).
For many-to-many-relations this is the owning-side:
#OrderBy
#ManyToMany
#JoinTable(name="`STUDENT_TO_TEACHER`", joinColumns = {
#JoinColumn(name="`student_id`", referencedColumnName="`id`", nullable=false),
}, inverseJoinColumns = {
#JoinColumn(name="`teacher_id`", referencedColumnName="`id`", nullable=false)
})
public Set<Student> getStudents() {
return this.students;
}
And the non-owning-side:
#ManyToMany(mappedBy="students")
public Set<Teacher> getTeachers() {
return teachers;
}
Now why owning-side and non-owning side is important:
Student student = ...
Teacher teacher = ...
// a bad example:
student.getTeachers().add(teacher); // STUDENT.TEACHERS IS NOT THE OWNING SIDE
entityManager.persist(student); // THIS IS NOT POSSIBLE!
// a good example
teacher.getStudents().add(student); // good
entityManager.persist(teacher); // possible, teacher have a new student.
There is another rare case of mapping beside this 1-1/n-m/1-n sides the Map<> association. The Map<> association let you use a map as a getter in hibernate. I never used it so I can not elaborate experience in this.

How to retrieve an Entity Object just with #Id (Proxy object), check if it exists and assign it to a #ManyToOne association

I have an entity Product which have many fields and associations (around 60).
And a table ProductView which has a #ManyToOne(fetch = FetchType.LAZY) association with Product.
Is there a optimal way to retrieve Product object and assign it to ProductView ?
If its used JPA findById(productId) or JPQL/EntityManager selects-> It will retrieve all products fields and associations
Product product = productRepository.findById(productId);
ProductView productView = new ProductView(product);
save(productView);
If its used JPA getOne -> It solves the problem but the Proxy can throw error if Product does not exists. And this error can not be handled because it happens at runtime.
Product product = productRepository.getOne(productId);
ProductView productView = new ProductView(product);
save(productView);
If a DTO is used or Interface which refers to the same Product Table -> We will get just an object with Id field, but a lot more processes will need to be added (Which I am not familiar with)
Delete foreign keys from ProductView table (#ManyToOne -> #Column) and simple assign productIds. But in this way, there will be no logic connection between tables.
ProductView DB
How usually developers avoid this problem ?
I don't understand what the problem is. Just use getOne approach and at the end of your method, use flush which will throw the constraint violation exception that you can handle. This is the way to go.

Delete Values from Join Table spring boot

I have two tables students and subjects. A student can have more than one subject and vice versa. I have two model classes and vave joined using Many to Many relationship in spring boot and JPA.My problem is how I can delete values from my join table. But I can't figure out how I can do delete from join table. For Student and Subject Model I delete comfortably using deleteById() function.This is my code:
#ManyToMany
#JoinTable(
name = "student_subject",
joinColumns = #JoinColumn(name = "student_id"),
inverseJoinColumns = #JoinColumn(name = "subject_id"))
private Set<SubjectModel> subjects;
//and my repository Class
#Repository
public interface SubjectDao extends JpaRepository<SubjectModel, Integer> {}
You have to delete the corresponding objects form both sides of the link, and then save them.
myStudent.getSubjects().remove(mySubject);
mySubject.getStudents().remove(myStudent);
SubjectDao subjectDao = new SubjectDao();
subjectDao.save(mySubject);
Here another examle: Hibernate: delete many-to-many association
You have two table Student and Subject.
And I suppose you want is delete one of the subject from a student.
For that you should let jpa delete the row from subject and student-subject association table. And dont need to user SubjectRepository.
Take a look.
Student firstStudent=studentRepository.findById(1);
Set<SubjectModel> subs=firstStudent.getSubject();
subs.clear();
firstStudent.setSubject(subs);
studentRepository.save(firstStudent); // this method will delete the row from assiciation table as well as the subject table.

Laravel relationship between two tables

I'd like your input on this.
I have a Customer_table with a field name. I have another table called Reservation_table with a Customer_name field.
How can I relate them in such a way that I'd see all the bookings by the specific customer?
In Reservation_table you should have a field(foreign key) userid in order ta have a user for each reservation.
You can using primary key - foreign key relationship to relate/join those two tables. Also, instead of having a 'Customer_name' field as your FK referring to 'name' field in 'Customer_table' table, it is better to have an id (unique) generated for each customer; This way you can have an efficient way of uniquely identifying and relating customer across tables; can save space on Database side as well. Hope this helps!
If you want to use eloquent you must first define a relationship.
One reservation belongs to a user. Here is how to define the relationships:
Inside the Reservation model:
public function user()
{
return $this->belongsTo('App/User'); //User model
}
To define the inverse you do the following:
Inside User model:
public function reservations()
{
return $this->hasMany('App/Reservation'); // Reservation Model
}
Now you can do the following in your controller:
$reservations = Auth::user()->reservations;
Now you have all reservations by the currently logged in user.
I am not sure if I got the question right so ask away.

Eloquent Eager Load Double Relationship

This one's been bothering me and Google hasn't been of any help. I have two models, a Dance model and an Author model. The relationship is that an author can have many dances. The wrinkle is that there are actually two relationships between these objects, as there is the original author and an author much later credited with reconstructing the dance (these are historical dances, after all). I can eager load with the load() function for the relation that uses the normal foreign key, but I cannot find out how to eager load the relation that uses a differently-named foreign key.
How do I do eager loading on this second relation?
When setting up a relationship with a different foreign key you have to specify in the relationship which key you wanna use...return $this->hasOne('Author', 'foreign-key');
So if I understand your question you wanna setup a relationship to two authors, in the same author table....
So maybe something like this then?? (replace foreign_key with your table field)
public function orig_author(){
return $this->hasOne('Author');
}
public function second_author(){
return $this->hasOne('Author', 'foreign-key');
}
public function dance(){
return $this->hasMany('Dance');
}
Then just retrieve it like so...($id being the id of your dance)
$dance = Dance::with('orig_author','second_author')->find($id);
But to be honest, I've never tried having a double relationship with a table.....let me know if it works out for you. :) Id be very interested.
You can do this:
$dance = ModelName::query()
->with('eagerNameOne')
->with('eagerNameTwo')
->find($id);
where ::query() was added only tu put all the eagers on the same identation level.

Resources