OneToOne JPA issue - spring-boot

I have 2 class
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String age;
#OneToOne
#JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
}
and
public class Address {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String building;
private String country;
#OneToOne(mappedBy = "address")
private User user;
}
in my table address, I have a few rows.
When I insert table user with data
{
"id":null,
"name":"Foo",
"age":"18",
"address":{
"id":1,
"building":"Too",
"country":"ABS"
}
}
Table user have 1 row with address_id =1.
I insert same data as above
Table user have 2 row with address_id =1.
My answer is: why 2 table connected by one to one can happen the above case?

You can find your answer here
Why #OneToOne is allowing duplicate associations?
Basically, #JoinColumn(name = "address_id", referencedColumnName = "id") alone doesn't serve the semantics of one-to-one in the database, you need to add unique=true into the #JoinColumn, which makes it #JoinColumn(name = "address_id", referencedColumnName = "id", unique = true).
Side-note: I suggest you drop your tables and then re-creating them before trying this out. If you are using Hibernate, you can set hibernate.hbm2ddl.auto to create-drop

Related

JPA composite key spring boot

I made 2 one-to-one relationships with 2 foreign keys, but I can't make a constraint or how could I make the 2 unique keys be a unique key in the new table?
#Table(name = "cart")
public class Cart {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
private int quantity;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "product_id")
private Product products;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private User users;
}
#Entity
#Table(name = "Products")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private int quantity;
private Double price;
private String image;
It spells my 2 keys correctly, for example
user_id = 2 , product_id =2 would be ok
but if I enter another user_id=2, product_id=2 should not work, but for me it is entered in the database
You can use #PrimaryKeyJoinColumn in the #OneToOne relation:
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn(name = "product_id", referencedColumnName = "id")
private Product products;

JPA onetomany mapping showing nested data many times

I have two table user(id,name) and user_mails(id,email,user_id) user to user_mails have one to many relation.
I have created following entity in spring boot
User
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
#Column(name = "name", nullable = false)
private String name;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<UserMail> userMails =new HashSet<UserMail>(0);
//Getter setter and constructor
}
UserMail
#Entity
#Table(name = "user_mails")
public class UserMail {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(name = "email", nullable = false)
private String name;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "user_id")
private User user;
It is showing following output on calling controller
[{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":
and more
I want to access all users with all mail ids also want to acces mail id with user details
What changes should I do to get proper result

ManyToMany relation use in service

Job entity
#Column(name = "name")
private String name;
#ManyToMany
#JoinTable(name = "user_job",
joinColumns = #JoinColumn(name = "job_id"),
inverseJoinColumns = #JoinColumn(name = "user_id")
)
private List<User> user;
User entity
#Column(name = "email")
private String email;
#ManyToMany
#JoinTable(name = "user_job",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Set<Role> roles;
Role entity
#Column(name = "name")
private String name;
#ManyToMany(mappedBy = "roles")
private Set<User> users;
Here we have a table user_job with 3 ids and I want to insert data in service layer. How I can do it and what repository I should implement or use existent like user/role/job?
class UserJobService{
public void setUserJob(User user, Job job, Role role){
}
}
The problem with #ManyToMany association is you can't delete a record directly from user_job table, using Hibernate. To delete the record, you need to load a user with all his jobs. So better to add UserJobEntity
#Entity
#Table(name = "USER_JOBS")
class UserJobEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "USER_ID")
private User user;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "JOB_ID")
private Job job;
}
public UserJobEntity createUserJob(UserEntity user, JobEntity job) {
UserJobEntity userJob = new UserJobEntity();
userJob.setUser(user);
userJob.setJob(job);
return userJobRepository.save(userJob);
}
Probably you will want to add (user, job) unique constraint to user_jobs table.
Some advices
Use plurals for table names. user_jobs in place of user_job
Role is tabular data. So it shouldn't have a users List.
Don't use Set for associated collections. Definitely you will encounter "multiple bugs fetch exception" and this exception will help you to change queries. With Set you can have large cross products and even don't notice them.

Spring data JPA populate data of 2 One-To-Many relationship

I have a ManyToMany relationship that is broken down into 2 OneToMany relation. A Book can belong to multiple Categories and a Category can have many Books.
When I query for Book, the categories list just get empty. How can I get a list of all Categories that a Book belong to ? Am I missing something ?
#Entity
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#NotBlank(message = "Please input book title")
private String title;
private Integer publishYear;
private String publisher;
private String language;
private Integer numberOfPages;
private String avatarUrl;
#OneToMany(targetEntity = BookCategory.class, cascade = CascadeType.ALL)
#JoinColumn(name = "category", nullable = false, insertable = false, updatable = false)
private Set<BookCategory> categories = new LinkedHashSet<>();
}
#Entity
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(nullable = false)
#NotBlank(message = "Please input category name")
private String name;
}
#Entity
public class BookCategory {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#ManyToOne
#JoinColumn(name = "book", nullable = false)
private Book book;
#ManyToOne
#JoinColumn(name = "category", nullable = false)
private Category category;
}
Try using mappedBy attribute with #OneTOMany annotation on the 'One' side of the OneToMany relation.
Or you can also try using the following:
#ManyToMany
#JoinTable(
name = “book”_category,
joinColumns = #JoinColumn(name = “book_id”),
inverseJoinColumns = #JoinColumn(name = “category_id))
Read more:
https://vladmihalcea.com/the-best-way-to-use-the-manytomany-annotation-with-jpa-and-hibernate/

Map primary key to composite key in JPA

I have 2 tables namely user & user_session.
User table has user_id as a primary key which is referrers to user_session table.
Plus user_session has composite key including session_intime and user_id.
I have designed my entity in JPA. Now I want to map these two entities. I have tried to map these two tables. But my application build failed. Can you please help me out?
#Entity
#Table(name="user")
public class User {
#Id
#Email
#Column(name = "user_id")
private String userId;
#Column(name = "password")
private String password;
#Column(name = "fname")
private String fname;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "userId", referencedColumnName = "user_id")
private UserSession userSession;
}
#Entity
#Table(name="user_session")
public class UserSession{
#EmbeddedId
private UserSessionPK userSessionPK;
#Column(name = "remote_ip")
private String remoteIp;
}
#Embeddable
public class UserSessionPK implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "user_id")
private String userId;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "time_in")
private Date timeIn;
}
I want to map user_id of User table to user_id of UserSessionPK. I am new to JPA, so I don't know how to map with embeddable class.
Remove the mappedBy attribute. This attribute is used when you have bidirectional relationship to indicate which side of the relationship is the owner.
But you will need to set the Foreign Key aka JoinColumn
#JoinColumn("user_id")
#OneToMany(fetch = FetchType.LAZY)
private UserSession userSession;

Resources