ForeignKey between User and UserRole with Spring Security - spring

Actually i have an authentication that works with rbac.
The problem is that, i encoutered a case where a user was deleted, but in the database, the user id and role were still present.
When the user was recreated he got the roles of a former user who had this id.
Acutally i can't delete user role of a user that has been delete because it's an enum..
Is it possible to create a relationship between users and roles while keeping this enumeration principle? Or another solution ?
public class AppUser {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
....
#ElementCollection(fetch = FetchType.EAGER)
#Enumerated(EnumType.STRING)
List<AppUserRole> appUserRoles;
}
public enum AppUserRole implements GrantedAuthority {
ROLE_ADMIN, ROLE_DEMO;
public String getAuthority() {
return name();
}
}

When deleting an entity with an #ElementCollection the delete is cascaded automatically. When doing this through SQL this (might) not be the case, depending on how cascade rules are applied in your database.
But with your setup that should happen automatically.
See also https://stackoverflow.com/a/7696147/2696260

Here is an example of how the roles table for the #ElementCollection can be created (PostgreSQL syntax):
CREATE TABLE user_roles (
user_id int,
role text,
PRIMARY KEY (user_id, role),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
The foreign key with the ON DELETE CASCADE makes sure that the associated roles are deleted when user is deleted.

Related

How can I reuse an #Id column for a composite key in a JPA Repository?

I have an Activity object. An Activity belongs to a User. An Activity can be assigned a Category. A Category also belongs to a User.
#Entity
public class Activity {
// id column omitted
#ManyToOne(cascade = CascadeType.ALL)
private User user;
#ManyToOne(cascade = CascadeType.ALL)
private Category category;
// other properties omitted ...
}
This creates a table
Activity
id
user_id
etc...
The Category is essentially just a name, so I want [name + user] to be its composite key.
#Entity
public class Category {
#Id
#ManyToOne
private User user;
#Id
private String name;
}
This creates a table
Category
name
user_id
But then also adds the composite key to the Activity table
Activity
id
user_id
category_name
category_user_id
which is of course needed, and functional, but not ideal.
I would like to use the existing user_id column in the Activity table to be used for the foreign composite key. Functionally, the Activity's User will always be the Category's User, and my application logic will make it so.
Activity
id
user_id
category_name
where [user_id + category_name] forms the foreign composite key.
How do I structure this in my objects? and how do I annotate it using JPA so the tables are how I want them?

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

Spring Boot JPA Bidirectional Mapping without Foreign Key

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

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.

join between two table in spring and hibernate Mysql

Table 1 name is users field name is userid ,roleid and username
Table 2 name is roles field name is roleid and rolename
I want to create relation between these two table.
I have follows more than 10 example. but i have not got any result.
Please help me and create the code according to me
Thanks
In order to create a relation between two entities/tables, you need to determine the type of relation you want to represent, whether that is a one-to-one, one-to-many, many-to-one, or many-to-many.
For your use case between a User and Role, this is typically a many-to-many because a User is associated to many roles and a role may be associated to many differing users.
User.java:
#Entity
public class User {
/* other things */
#ManyToMany
#JoinTable(name = "user_roles")
private List<Role> roles;
}
Role.java
#Entity
public class Role {
#ManyToMany(mappedBy="roles")
private List<User> users;
}
In this particular example, the relationship is owned by the User beacuse typically you would have roles created separately and then you associate a user to a set of roles.

Resources