Deyan Perov wrote:A town is the OWNER of a relationship.
To tell Hibernate who is the owner we use @OneToMany(mappedBy = "townEntity").
And this means in the Student table it will be created foreign key town_id, right?
@JoinColumn(name = "town_id") - I just don't see the difference when I have this and don't understand when to use it because I saw codes without it too. I read it about it but...Probably I missed something more from relationships to understand when I have to use it. I am not sure when I need it and what exactly does it when I "get" the same with mappedBy.
Before I ask about JSON annotations let me say about the other problem.
This works, when I POST Student it creates the Student and his Town. When I create another Student with the same Town name it has the id from that Town (id = 1) but when I change some attribute in Student and want to PUT it I get some changes. A new Town is created with the same name and has id = 2, the Student which I updated now has foreign key town_id = 2. Why?
I want to have to Create, Read, and Update a Town. I don't need it deletes. But when I change a Student and if I don't touch a Town information I want to stay the same.
To avoid infinite JSON loop I use and . But when I want to GET a Student it doesn't show my any data of his Town. I found this can help me but I am not sure is that what I need it
Because when I GET a Student Postman backs me the Student with his Town and the Town has an array of all Students who have FK of that Town.
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
Deyan Perov wrote:
I have Town which can have many Students. Student(s) can exist without Town and Town can exist without Student(s).
Paul Clapham wrote:I gave you a cow for such a comprehensive answer, Rob. I also gave Deyan a cow for posting such a well-formed comprehensively-answerable question.
Dave Tolls wrote:
Deyan Perov wrote:
I have Town which can have many Students. Student(s) can exist without Town and Town can exist without Student(s).
Rob's covered everything, but I didn't notice whether he spotted this.
You say a Student doesn't have to have a Town...OK, but your StudentEntity has its TownEntity marked as NotNull.
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
On a JPA level, the one without mappedBy is the owner. By default with @ManyToOne / @OneToMany, that means the MANY side.
It's possible to change the owner to Town, but that means that you should remove the (explicit) relationship from the Student side, basically creating a unidirectional relationship.
@ManyToOne on Student. Town doesn't even need @OneToMany to get the foreign key; it's a unidirectional many-to-one without it.
@OneToMany without mappedBy on Town, and no @ManyToOne on Student. This is a unidirectional one-to-many.
@OneToOne with mappedBy on Student. Note that the non-owner side needs mappedBy with @OneToOne.
By default, the JPA provider tries to guess the column name. It does this by taking the entity name and appending _id. By using @JoinColumn you can make it explicit, or override the default.
Any entity without an id will be considered new, and will trigger an insert. If you update a Student, that Student has an id. If its Town does not, the cascade will cause a new one to be created. That's because CascadeType.ALL implies PERSIST. In order to update the Town as well, it needs to have an id before saving the Student.
One interesting thing about your Town. It looks more like an Address. I understand that multiple Students can live at the same Address. But how would you support moving a Student to a different Address? If you update the existing one, all other Students at the same Address will belong to the same updated Address. It would appear that all of the Students moved instead of just the one. This is something to think about carefully.
I hate directly exposing entities, because you have to work hard often to prevent these loops. It will give you more problems than you want. Instead, I prefer to create a DTO class for the REST interface. These don't have the bidirectional relationship, just the one you want. For creating you'd have to convert the DTO into an entity and save it; for updating you'd need to find the existing entity, update it from the DTO, and save it.
You say a Student doesn't have to have a Town...OK, but your StudentEntity has its TownEntity marked as NotNull.
Deyan Perov wrote:Rob Spoor, I want to thank you for all your effort to help! But now when I scratched deeper I am still confused and now I have many more questions...
On a JPA level, the one without mappedBy is the owner. By default with @ManyToOne / @OneToMany, that means the MANY side.
I always think the owner is ONE because I thought MANY of something depends on that ONE.
It's possible to change the owner to Town, but that means that you should remove the (explicit) relationship from the Student side, basically creating a unidirectional relationship.
I this case it will be created a new table and I will have 3 tables instead of 2. This can be prevent with @JoinColumn?
@ManyToOne on Student. Town doesn't even need @OneToMany to get the foreign key; it's a unidirectional many-to-one without it.
@OneToMany without mappedBy on Town, and no @ManyToOne on Student. This is a unidirectional one-to-many.
@OneToOne with mappedBy on Student. Note that the non-owner side needs mappedBy with @OneToOne.
This is new to me... First I have to understand bidirectional and unidirectional. Bidirectional doesn't exist in relational databases, there exist only undirectional, right? Table A has a FK from Table B, but Table B doesn't have a FK from Table A, right? And this is undirectional?
We need to bidirectional on the level of Java because we need to have a reference for an object in a class. i.g. We have a Student which HAS-A Town, Town HAS-A student. Am I right? The student has to know for the Town, and the Town has to know for the Student.
But if the Town doesn't have a reference of the Student is that undirectional then?
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
There will never be a third table when using @OneToMany / @ManyToOne / @OneToOne unless you explicitly tell JPA to use one. A unidirectional @OneToMany will still use a join column in the MANY table; the MANY entity just doesn't use it itself. With @JoinColumn you tell JPA explicitly what the column looks like instead of having JPA using its defaults.
Deyan Perov wrote:
There will never be a third table when using @OneToMany / @ManyToOne / @OneToOne unless you explicitly tell JPA to use one. A unidirectional @OneToMany will still use a join column in the MANY table; the MANY entity just doesn't use it itself. With @JoinColumn you tell JPA explicitly what the column looks like instead of having JPA using its defaults.
I mean by this: https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/ Unidirectional @OneToMany
As you can see I am not conformable with JPA, Hibernate, and Relationships. Could you please suggest to me some good documentation where I can read about it? I am going to search over coderanch too, maybe I will find some interesting text which can help me not to be confused.
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
One interesting thing about your Town. It looks more like an Address. I understand that multiple Students can live at the same Address. But how would you support moving a Student to a different Address? If you update the existing one, all other Students at the same Address will belong to the same updated Address. It would appear that all of the Students moved instead of just the one. This is something to think about carefully.
Deyan Perov wrote:I believe the book is good but right now I prefer to read some shorter documentation. Because this is important to finish this in next period.
Those blogs: vladmihalcea, thorben-janssen and baeldung are very good but I think it will be more helpful for me when I become much better at understanding JPA, Hibernate, and Relationships.
Can you suggest some shorter documentation?
I want to make small changes in my code. What do you think about those changes?
I created class TownEntity because in need of this class to add a reference to StudentEntity and CompanyEntity.
Maybe from TownEntity to remove address and to put the separate attributes in StudentEntity and CompanyEntity?
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
Deyan Perov wrote:When I remove PERSIST it still creates the Town or Student, only where I saw affect is when I put CascadeType.REMOVE. If I remove a Student it will remove his Town too. Then I created two students and one town and when I remove the student id = 1 it removed both students and town.
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
Cascades bubble "down".
In your example, any of the listed operations performed on Town will also be performed on all of the Students stored in the list.
Did you persist the Student before persisting the Town? Because otherwise the Student shouldn't have been persisted.
Be aware with REMOVE. Only use it if your entities are really tied together. If a Student can live without a Town, removing the Town should usually leave the Student intact. If you use REMOVE (or ALL) on every relationship, you can end up removing many records by just removing one. You'd need to first break the relationship (by removing the link between the two) before removing to prevent this.
Deyan Perov wrote:
Cascades bubble "down".
Sorry, I don't get this.
In your example, any of the listed operations performed on Town will also be performed on all of the Students stored in the list.
Does this mean because I wrote this - @OneToMany(mappedBy = "townEntity"...) or because it this annotation is in TownEntity class?
Did you persist the Student before persisting the Town? Because otherwise the Student shouldn't have been persisted.
This is how I persist the Student.
Be aware with REMOVE. Only use it if your entities are really tied together. If a Student can live without a Town, removing the Town should usually leave the Student intact. If you use REMOVE (or ALL) on every relationship, you can end up removing many records by just removing one. You'd need to first break the relationship (by removing the link between the two) before removing to prevent this.
Thank you for suggestion.
In my case I should left these:
But what about the other side, above attribute TownEntity? I don't see any affect do I left CascadeType.ALL or put only any other cascade. I know if I don't have any cascade it will be CascadeType.ALL by default.
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
That feels good. Thanks. Here's a tiny ad:
the value of filler advertising in 2020
https://coderanch.com/t/730886/filler-advertising
|