Many to many table with an additional id column - mysql

In hibernate if i do the following
class User{
#ManyToMany
private List<UserRole> roles;
}
it creates a separate table User_UserRole where there is two column (user_id and roles_id)
But i want a third column in there e.g "id" which uniquely identify each row and the id's are auto generated.
How do I Do this ???

with default behavior you cannot achieve this, but if you can create the table by yourself in the database (instead of letting hibernate doing it) and then mapping
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "User_UserRole", joinColumns = { #JoinColumn(name = "USER_ID") }, inverseJoinColumns = { #JoinColumn(name = "ROLES_ID") })
private List<UserRole> roles;
of course you will make the id column autoincrement also in the table definition.

You could do that with the following implementation
#Entity
class User{
#Id
private int id;
#OneToMany(mappedBy=role)
private List<UserRole> roles;
}
#Entity
#Table(name="USER_ROLE")
class UserRole{
#Id
private int id; <--ID you were looking for
#ManyToOne
private User user; <--User ID
#ManyToOne
private Role role; <--Role ID
}
#Entity
class Role{
#Id
private int id;
#OneToMany(mappedBy=user)
private List<UserRole> roles;
}
Trick is break ManyToMany relationship in two OneToMany pointing to the Jointable. This works !!
Also you can add another columns in the USER_ROLE table, without breaking anything

Related

How to bypass MapsId for a single default case

I have created an Employee entity and a corresponding ProfilePicture entity:
#Entity
#Table(name = "employee")
public class Employee{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
}
#Entity
#Table(name = "profile_picture")
public class ProfilePicture {
#Id
private Long id;
#OneToOne
#MapsId
private Employee employee;
#Column(name = "image")
private byte[] image;
}
Now, I want to add a default image to my profile_picture table. I am using a MySQL database and introducing a default image seems to be a problem, since my profile_picture database entries require an association with an employee. The issue is that MapsId is trying to map the id of the associated employee to the id of my profile-picture. When there is no associated employee, this is impossible.
Does anyone have an idea how to solve this problem? I know I could create a dummy employee, but I don't want to do this. I would like to have an entry in my profile_picture table for which the employee_id column is simply null. Right now, however, this is violating some constraints. I know I will have to think of a different solution, I am just asking for ideas.

#OneToOne JPA - create ID on non parent side

I'm use Spring Boot and trying to use #OneToOne JPA annotation . My class looks like this:
Primary Class
#Entity
public class User {
....
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id", referencedColumnName = "userID")
private ForeignProfile userForeignProfile;
}
Second Class:
#Entity
public class ForeignProfile {
#Id
private Long id;
private Long userID;
.....
#OneToOne(mappedBy = "userForeignProfile")
private User user;
}
I want no additional columns to be created and this 2 tables to be connected using 'id' from User table and userID from ForeignProfile table. I tryed a lot of combination but cant make it work. The configuration I have shown here doesn nothing. What I'm doing wrong?
I tried using this examples but they don't do what I need
https://www.baeldung.com/jpa-one-to-one

Foreign Keys in Spring Boot (MySQL, Hibernate, JPA)

I am trying to write a RESTful API using Spring Boot and I am not able to figure out a way to map my relations in the database. I have a User and a Reports table. Each User can have multiple Reports, and a single report consists of "FROM USER" and "TO USER" columns to indicate who sent the report and to whom. My User ID is the primary key and for the Report table, I am generating REPORT ID as the primary key using AUTO INCREMENT. Here is my User model class -
#Entity
#Table (name = "user")
#EntityListeners(AuditingEntityListener.class)
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String email;
private String password;
#OneToMany(mappedBy = "user",cascade = CascadeType.ALL)
private List<Report> reportReceivedList;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Report> reportSentList;
/* Getters and setters ..... */
}
Here is my Report Model class -
#Entity
#Table (name = "report")
#EntityListeners(AuditingEntityListener.class)
public class Report {
#Id
#Column (name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne()
#JoinColumn(name = "from_user_id")
private Long fromUserId; //THIS SHOULD BE FROM "USER" TABLE
#ManyToOne()
#JoinColumn(referencedColumnName = "to_user_id")
private Long toUserId; //THIS SHOULD BE FROM "USER" TABLE
#Temporal(TemporalType.DATE)
#CreatedDate
private Date createdAt;
private String observation;
private String context;
//Other variables and getters and setters .....
}
Can someone please show me a way to correctly define this relationship. My current model doesn't work. Also, I want rows from REPORT class to be deleted as soon as a user is deleted. Thanks!
I finally fixed it by changing my User class as follows -
#OneToMany(cascade = CascadeType.ALL, targetEntity = Report.class)
#JoinColumn(name = "to_user_id")
private List<Report> reportReceivedList;
#OneToMany(cascade = CascadeType.ALL, targetEntity = Report.class)
#JoinColumn(name = "from_user_id")
private List<Report> reportSentList;
And by changing my Report class as -
#Column(name = "from_user_id")
private Long fromUserId;
#Column(name = "to_user_id")
private Long toUserId;

Spring Data JPA (Hibernate) is not creating column as autoincrement

Why is this mapping unable to create the column id as autoincrement?
#Entity(name = "user_role")
public class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", nullable = false, unique = true)
private Long id;
#OneToOne(cascade = CascadeType.MERGE, targetEntity = Role.class)
#JoinColumn(name = "role_id")
private Role role;
#OneToOne(cascade = CascadeType.MERGE, targetEntity = User.class)
#JoinColumn(name = "user_id")
private User user;
}
Thanks in advance!
To use a AUTO_INCREMENT column in your MySQL, you are supposed to use an IDENTITY strategy:
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "id", nullable = false, unique = true)
private Long id;
//Your code
To learn more check this Link
It is clearly mentioned that
The IDENTITY strategy also generates an automatic value during commit for every new entity object.
Well, just to help people.
The problem was the name of my entity "user_role", I don't know why but after changing the entity name to "userrole" everything worked and the id column was created as AUTOINCREMENT.
Hope this helps!

How to fetch data from One To One Relationship in SubQuery using Hibernate in spring

I have two table hesk_users, user as under.
#Entity
#Table(name="hesk_users")
public class UserHesk {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column
private int id;
#OneToOne
#JoinColumn(name="user_id")
private User user;
set.... get..
}
#Entity
#Table(name="user")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#NotEmpty
#Column
private String firstname;
#OneToOne(mappedBy="user")
private UserHesk userHesk;
set ... get ...
}
I have hibernate query but it not working..
DetachedCriteria detachedCriteria=DetachedCriteria.forClass(UserHesk.class)
.setProjection(Projections.property("user_id"));
Criteria criteria=sessionFactory.getCurrentSession().createCriteria(User.class);
criteria.add(Property.forName("id").notIn(detachedCriteria));
User user=(User)criteria.list().get(0);
System.out.println(user.getFirstname());
System.out.println("Subquery Size "+criteria.list().size());
Error for user_id filed. which can not be get because of relationship.
HQL and criteria queries always use the entity classes and properties. Never the names of the underlying tables and columns. The UserHesk class doesn't have any user_id property. It has a user property.
So the code should be
DetachedCriteria detachedCriteria =
DetachedCriteria.forClass(UserHesk.class)
.setProjection(Projections.property("user.id"));
or even
DetachedCriteria detachedCriteria =
DetachedCriteria.forClass(UserHesk.class)
.createAlias("user", "u")
.setProjection(Projections.property("u.id"));