Do I need to recreate database relationships in java spring if they already exist in the database? [closed] - spring

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.

Related

#JoinColumn and how it links two tables

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

I am using Spring boot jpa with Restful api services to insert multiple users in array or list

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)

how to make a spring jpa/correct repository when having mandatory relationships?

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.

Postgresql and Spring Roo Binding serial type for ID

I am having trouble using the Postgresql serial type in Spring Roo. What I want is to have the an auto-incrementing id column which will work with the auto generated entity classes in Roo.
The Postgresql sequences, which are generated with the default way of doing things in Spring Roo, work fine within the spring application. But sometimes I have to manually insert rows in the database using sql. (the sequences dont seem to work properly when I do an INSERT INTO... statement). If I could use serial type, then manual INSERTS are easy.
For example I have an office entity and and employee entity. There is a many-to-one relationship between employees and offices.
Here is my class for the Office entity.
#RooJavaBean
#RooToString
#RooJpaActiveRecord
public class Office {
#Id
#Column(name="officeid", columnDefinition = "serial")
#Generated(GenerationTime.INSERT)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long officeid;
/**
* Office Name
*/
#NotNull
#Size(max = 100)
private String name;
}
While this does work when my test inserts an office record, it fails when an employee record is inserted since the officeid foreign key value is null. (I guess it needs to flush between the office insert and the employee insert, but the auto-generate tests dont seem to do that.)
So what is the proper annotations to use to tell Roo (and hibernate/jpa) to use the serial data type, and also to work properly with inserts and relationships within the spring application?
Roo generates default JPA annotations, you must customize and setup them as needed. Note Roo guarantees your changes won't be modified.

self referencing object in JPA

I am trying to save a SystemUser entity in JPA. I also want to save certain things like who created the SystemUser and who last modified the system User as well.
#ManyToOne(targetEntity = SystemUser.class)
#JoinColumn
private SystemUser userWhoCreated;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(iso=ISO.DATE_TIME)
private Date timeCreated;
#ManyToOne(targetEntity = SystemUser.class)
#JoinColumn
private SystemUser userWhoLastModified;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(iso=ISO.DATE_TIME)
private Date timeLastModified;
I also want to ensure that these values are not null when persisted. So If I use the NotNull JPA annotation, that is easily solved (along with reference to another entity)
The problem description is simple, I cannot save rootuser without having rootuser in the system if I am to use a DataLoader class to persist JPA entity. Every other later user can be easily persisted with userWhoModified as the "systemuser" , but systemuser it's self cannot be added in this scheme.
Is there a way so persist this first system user (I am thinking with SQL). This is a typical bootstrap (chicken or the egg) problem i suppose.
Have you tried rootUser.setUserWhoLastModified(rootUser) ?

Resources