Spring Boot JPA Bidirectional Mapping without Foreign Key - spring-boot

Is it possible to Greate DDL using JPA with bidirectional mapping and without foreign key? If can, is it best practice?
#Entity
class Book{
int id;
String title;
#OneToMany(mappedBy="book")
Set<BookDetail> book_detail;
}
#Entity
class BookDetail{
int id;
String name;
String description;
#ManyToOne
Book book;
}

Yes. It is possible using a join table. It will have foreign keys of course.
#Entity
class Book{
#OneToMany
List<BookDetail> bookDetail;
}
#Entity
class BookDetail{
#ManyToOne(fetch = FetchType.LAZY)
Book book;
}
what is #JoinColumn and how it is used in Hibernate

You can't do it without at least one foreign key, since a DB needs to establish some connection between two entities - BookDetail and Book. It is possible to create two tables for these entities without a real foreign key by using plain integer attribute in BookDetail which will be storing a value of Book's id. But don't do that!
With a foreign key your DBMS generates constraints so it's known about the relationship and it prevents some unsafe deletions and insertions, so each BookDetail's row references existing Books one.
Without real foreign key you c accidentally remove a Book and you BookItem's

Related

Many to one mapping Hibernate

I am doing many to one mapping in hibernate. I am using the existing tables which I created earlier for one to many mapping (customer and order) but when I am trying to map and update those table I couldn't able to I don't know how should I processed? and I would like to insert the data meaning I would like to create some more orders using command line runner for that customer.
Could you please help me with this
Appreciate your help.
Mapping one-to-many and many-to-one association
Both associations are the same association seen from the perspective of the owing and subordinate entities and respectively.
Student one-to-many Address
Address many-to-one Student
#OneToMany annotation can be applied to a field or property value of "one" end entity class for a collection or an array representing the mapped "many" end of the association.
#ManyToONe relationship between two entities is by managing the FK(Foreign key) of the "one" end entity, as a column in the "many" entity table.
> **Bidirectional one-to-many using ```#JoinColumn```**
#Entity
public class Student{
#OneToMany(cascade = CasecadeType.ALL)
#JoinTable(name="Student_FK")
public set<Address> getAddress(){
return address;
}
}
One-to-Many side as the owing side, You have to remove the mappedBy element and set the #ManyToOne #JoinColumn as insertable and updatable to false. This Solution is not optimized and will produce some additional UPDATE Statement.
#Entity
public class Address{
#ManyToOne(cascade = CasecadeType.ALL)
#JoinColumn(name="STUDENT_FK", insertable = false, updatable = false)
public Student student;
}
For more details look at this link Link

How to establish foreign key relationship with a non entity table in the database using Spring data JPA?

My spring boot project uses an existing database, I have a new model entity/table in my project that must have a foreign key constraint with an existing table in the database.
I've tried to find solution online but all the answers are for the case where both the tables are present as entities in that project and using some #ManyToOne, #OneToMany annotations.
I can't define those annotations because I don't have the reference table as an entity or model in my project.
Let's say I have class like:
#Entity(name = "user")
public class User {
#Id
#GeneratedValue
private long userId;
private long departmentId;
I want to put a foreign key contraint on the departmentId column to reference to id column of the existing department table that isn't defined as a model or entity in my project.
Thanks
Just do it as normal
example
#Column(name = "department_id")
private Department departmentId;
You can later access it Department.departmentId. Hope this helps.
Try it like this
#ManyToOne
#JoinColumn(name="(column name of current entity)", referencedColumnName="(column name in target entity)")
private Department departmentId;
you can skip the referencedColumnName if the column name is same in both the entities

HQL join query: Path expected for join

I'm new to hql, I referred to a site to write hql query in Spring Framework, but it throws "Path expected for join!" exception
My query is
"from GaugeCateSelect cs inner join PreferredUrl purl on cs.survey=purl.survey where purl.uuid=:uuid"
I want to connect both table with "survey".
How can I sort it out?
Update
Two tables, names are GaugeCateSelect and PreferredUrl. The "survey" field is common for both table. uuid is in PreferredUrl. I want to get all data from GaugeCateSelect when I pass the uuid to PreferredUrl table. (In short, Pass uuid to PreferredUrl, then find the survey number from PreferredUrl and check the number with GaugeCateSelect table, if exists get all data)
Update 2
There is no primary/foreign key reference relationship between two tables. but common field survey is there
GaugeCateSelect class
class GaugeCateSelect {
private int id;
private String categoryName;
private int posNeg;
private Survey survey; //survey is in foreign key relationship of survey table
//Annotation, getters and setters were removed for easiness.
}
PreferredUrl class
public class PreferredUrl {
private int preferredUrlId;
private String uuid;
private int enabled;
private Survey survey; //survey is in foreign key relationship of survey table
//Annotation, getters and setters were removed for easiness.
}
Maybe you should check the Hibernate version you use as there is a difference when joining unrelated entities as discussed here: https://www.thoughts-on-java.org/how-to-join-unrelated-entities/

Spring JPA one to many

I have two entities :
#Entity
#Table(name="Registration")
public class Registration{
#Id
private UUID uuid;
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE}, fetch = FetchType.LAZY)
#JoinColumn(name="registration", nullable = false)
private List<Payment> payment;
}
#Entity
#Table(name="Payment")
public class Payment {
#Id
private UUID uuid;
/*#ManyToOne(targetEntity = Registration.class) <-- MappingException: Repeated column in mapping for entity
private Registration registration;*/
}
This entities create two tables :
TABLE `registration` (
`uuid` binary(16) NOT NULL,
PRIMARY KEY (`uuid`))
TABLE `payment` (
`uuid` binary(16) NOT NULL,
`registration` binary(16) NOT NULL,
PRIMARY KEY (`uuid`),
CONSTRAINT `FK_jgemihcy9uethvoe3l7mx2bih` FOREIGN KEY (`registration`) REFERENCES `registration` (`uuid`))
I'm using Rest Service. I can access to
registration.payment
but not
payment.registration
why ? I need a relation oneToMany bidirectionnal ?
Yes, you need to add the payment.registration #ManyToOne relationship if you use it in your code.
Take into account that JPA allows you to map a SQL database model to an object oriented one. Once you have the mapping between your objects and your database, you always work at the object level. That's why, although you have the relationship in the database, your Payment object doesn't know anything about it unless you map it to an attribute.
Of course it applies when you are using you data model objects or performing JPQL or Criteria queries. If you use native queries you have access to the database model as it is.

JPA/Hibernate - Create a table with foreign key only

How can create an entity table using Hibernate that will foreign keys in it a primary key. Consider it to a joining table (with few other attributes) between two tables having many to many relationship between them.
Any sample code?
Any real reason not to use a PK? If the entity has other attributes I would say you are better off with one.
If you really dont want one you can use JPA's #EmbeddedId using a compound key
private UserSessionId id
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "userId", column = #Column(name = "user_id", nullable = false)),
#AttributeOverride(name = "sessionId", column = #Column(name = "session_id", nullable = false)) })
public UserSessionId getId() {
return this.id;
}
public void setId(UserSessionId id) {
this.id = id;
}
Then you can define a separate entity UserSessionId that contains both FK's, at least this is how Hibernate Tools generates compound key relationships
If there are no extra fields involved in the join (ie. foreign keys only). You can use the following technique, no java domain object is required, hibernate will figure it all out for you.
http://www.mkyong.com/hibernate/hibernate-many-to-many-relationship-example-annotation/
You can still have other columns in your table such as creation_date, but their values will need to be updated at the database level.
There are very good examples of composed PK in the JSR document, take a look in JSR 317 in link for persistence-2_0-final-spec.pdf, 2.4 Primary Keys and Entity Identity section have great examples.

Resources