I am completely new to working with databases and a beginner to Spring Boot as well really so apologies for any wrong terminology/fuzzy logic. There are some similar questions to this on here but I have not found exactly the answer to what I was looking for so I decided to post. Ramble over.
I am reading an article about joining tables in Spring Boot. They have a teacher class and a course class and it is a one-to-many relationship. They don't have the full classes written out but it says that you can go into Teacher class and do:
#OneToMany
#JoinColumn(name = "TEACHER_ID", referencedColumnName = "ID")
private List<Course> courses;
or go to Course class and do:
#ManyToOne
#JoinColumn(name = "TEACHER_ID", referencedColumnName = "ID")
private Teacher teacher;
What threw me off is that the parameters given to JoinColumn were the same in both cases. Assuming that both tables have something called ID, how does Spring know which one to use? Does it start by looking at both tables, looking for teacher_id. Then, after finding that it switches to the other table to get the ID?
Actually this is in the methodology of One-To-Many mappings in relational databases.
To achieve 1-N relation you only need to have:
Table One -> primary_key
Table Many -> primary_key, fk_one_primary_key
With the above configuration, given a table One entity, you can get all it's Many relations using the primaryKey-foreignKey join, and vice versa.
Now, in the code you've shared, the two parameters are described as:
ID -> Primary key column of table One / Teacher
TEACHED_ID -> foreign key column of table Many / Course
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
When creating an entity in java spring, do I still need to specify the relationships that are already created inside the database?
For example, userId is a primary key in the 'user' table and a foreign key in the 'order' table, and they have a one-to-many relationship (a user can have multiple orders) and this relationship is created inside the database, do I need to recreate that relationship using the appropriate annotations in java spring?
Thank you.
It is not necessary, although it is recommendable because this way you can get your joins done without have to write a sql sentence using directly your jdbc driver.
The way to do this and most preferrable way if you are using spring is with springdata (with an orm that by default is hibernate). So you have to tag your entities with the #Entity annotation and mark each relation between entities with #ManyToOne or #OneToMany or if it is one to one adding it as an attribute of the other entity.
I suggest you to read this
https://spring.io/guides/gs/accessing-data-jpa/
The great advantage of using #OneToMany annotations etc..
is that the results of the links are created directly in the entity participating in the relationship.
As in the example here : https://hellokoding.com/jpa-one-to-many-relationship-mapping-example-with-spring-boot-maven-and-mysql/
#Entity(name = "BookCategory")
#Table(name = "book_category")
public class BookCategory {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "category_name")
private String name;
#OneToMany(
mappedBy = "bookCategory",
cascade = CascadeType.PERSIST,
fetch = FetchType.LAZY
)
private Set<Book> books;
....
books contains all the elements that satisfy the relationship.
If you use a search with Sql type Select * from mytable left join etc ... the could look different from your Entity with the result that you have to create a new object with which to manage query data.
I believe that all this is longer and more difficult to manage and maintain.
As I am new to Spring boot. I am not at all clear about mappings. By using #Onetomany mapping in one entity and #manytoOne mapping at other entities. Using the controller I have to write REST API functions to insert multiple users at a time inside an array or set. Can anyone please suggest some websites or provide some existing codes?
The #OneToMany and #ManyToOne mappings can be used according to your use-case, whether you need bi-directional mappping or not. For a simple example consider the following :
#Entity
#Table(name="ENTITY_A")
public class EntityA{
//...
#OneToMany(mappedBy="EntityA")
private Set<EntityB> entityBItems;
// getters and setters
}
#Entity
#Table(name="ENTITY_B")
public class EntityB{
//...
#ManyToOne
#JoinColumn(name="entityA_id", nullable=false)
private EntityA entityA;
public EntityB() {}
// getters and setters
}
What you need to look out for is the owning side of the relation indicated by the mappedBy . The owning entity can be used to persist and get the data from the database. But from the description in your question I cannot understand whether you actually need to use mappings at all as you just have to insert multiple users into a table without any relations to another entity. It will be more helpful if you could explain more about your use case and provide code samples for furthur analysis.
For details about the mappings article or article .
Official doc .
MappedBy signals hibernate that the owner of key (relationship) is on the other side.
This means that although you link 2 tables together, only 1 of those tables has a foreign key constraint to the other one.
MappedBy allows you to still link from the table not containing the constraint to the other table.
If you still want use #JoinColumn on both the Entities you can use #JsonManagedReference and #JsonBackReference from com.fasterxml.jackson
To save the multiple records at same time you can use yourRepository.saveAll(entities)
In my entity, I have defined a #ManyToOne(optional = false, cascade = CascadeType.PERSIST) to my other entity. The relationship works fine.
Now I am using Postgre DB where I have created my tables and defined foreign keys between columns in my tables. In my DB, those keys work. When I use my Spring Boot application with it, Spring for some reason creates hashed foreign keys (fk1sishw42l6qx85h5f3pckl6d0) instead using the ones that I have created. At least I think, it uses those.
Why is that so?
How to avoid that?
Hope this solution works, as it worked for me.
#ManyToOne
#JoinColumn(name="employeeID")
#ForeignKey(name='your_existing_constraint_name')
private employee employee;
I have the following database which allows users to rent books in a book shop:
The entity class Book needs to have a Category as well as BookDescription when saved.
Those Book class looks like this:
#Entity
#Table(name = "books")
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Book {
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "book_description_id")
private BookDescription bookDescription;
#ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
private Category category;
//omitted fields, getters, setters & other relations
}
I was checking out Spring Data JPA. It has a signature of
CrudRepository<T, ID extends Serializable>
which means that I will have
CrudRepository<Book, String>
but how will I save a book?
So, generally, the user will submit a form, I will bind a BookUIObject which will contain all the details needed to save a book, pass it to a BookService witch will extract from it 3 objects: Book ( a specific implementation), Category and BookDescription. The question is will the service hook up the book relations and call the general repository.save(Book) or it will call a method like repository.save(Book, Category, BookDescription)?
Also, should I bind directly the data from the user into entity classes, or do like I said, bind to a general BookUIObject and let the service extract from it the entity classes?
Kind regards,
Typically you will have to call BookReporitory.save(book). Book has cascaring Persist for both of the relations, so if you have set the BookDescription and the Category on the book instance you save, they will also be persisted. If you didn't have cascading persist, you would have to save them using their JPARepository (unless they already existed in the Persistence context).
One thing that is important to understand in this example is that if you create a new category object and set it on a book and save the book a new category is created in the DB. So if the UI posts category=sic-fi, you have to check if the category already exists, if it does then you must used the managed category, and set that on the book rather than creating another "sci-fi" category. This is the reason I would not have cascading persist on the Category relation, because I would rather have a constraint violation because a category didn't exist, instead of an new category sci-if when someone miss spelled it in the UI.
I do not recommending binding forms directly to JPA entities, because you always need to fetch entities from JPA, as you have to use the managed versions, so in my experience it is better to have another set of beans for form binding.
Another thing that jumps out if the lack of nullable=false in #JoinColumn. If a book can't exist without being in a Category it is vital that this is communicated to the database, and if you generate tables from the JPA metadata model, this is how it is done. If I could give only one recommendation when working with databases/JPA it is to be overzealous with NOT NULL. It is a 100 time easier to get a constraint violation when you insert, than to get a NullPointerException later and have to check every possible code-path that could end up calling save and checking if the argument could be null.
In addition I would recommend that you set of some time to understand the concept of the EntityManager and the Persistence Context, most of the mistakes/assumptions developers make come back to the persistence context and how the 4 entity states work.
I'm not sure if this is possible to do in Spring 3 framework using hibernate and mysql but I would appreciate any help. I have two classes - Employee and Examiner. The examiner is an employee and an employee is also an examiner. At the same time each Examiner can examine one or more employees and an employee can only have one Examiner.
Basically what I want to know is if it is possible to show the inheritance between the Employee and Examiner, and at the same time map a unidirectional one to many from Examiner to Employee?
What I have so far - the Examiner table with the inheritance constraint:
CREATE TABLE `examiner` (
`employee_id` varchar(255) NOT NULL,
`employee_name` varchar(255) NOT NULL,
PRIMARY KEY (`enployee_id`),
FOREIGN KEY (`employee_id`) REFERENCES `employee` (`employee_id`)):
The employee table:
CREATE TABLE `employee` (
`employee_id` varchar(255) NOT NULL,
`employee_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`employee_id`)):
I was thinking of a join table for showing the one to many behaviour but getting a compsite key for the table is not possible as I have a primarykeyjoin column.
I would appreciate any help in pulling this together as I have been stumped for days.
Java doesn't allow multiple inheritance, so unless you are using an interface I am not sure how you plan to make the two described classes instances of each other.
You could just make a class called EmployeeExaminer, and make it reference itself. With annotations it might look something like:
#Entity
public class EmployeeExaminer {
#ManyToOne
private EmployeeExaminer getExaminer() {/*...*/}
#OneToMany
private List<EmployeeExaminer> getEmployees() { /*...*/}
}
Documentation on the annotations can be found here.
Thanks #CodeChimp for your replies. I ended up following the first suggestion, and created a Self Reference class with the #onetomany and #manytoone annotations. The helper class for it works. I just have some problems implementing a controller and jsp page for adding the parent/child. But I will make a new question for that. Thanks again.