JPA Many-To-Many Duplicates - jpa

I have two entities with a many-to-many relationship in my spring boot project:
#Entity
public class Competition
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToMany(targetEntity = Kind.class, cascade = CascadeType.ALL)
private Set<Kind> kind;
...
}
and
#Entity
public class Kind
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
Unfortunately it is possible to create duplicates with the same name value. Any ideas how I avoid this?

Related

Spring Data Jpa OneToMany save bidirectional

I have a problem with saving child entities.
Here is my example. My model classes look like this:
#Entity
public class ImportDocument {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
private boolean imported;
#Transient
private Status status;
#Basic
private char statusValue;
#OneToMany(mappedBy = "importDocument" , cascade = {CascadeType.ALL})
private List<ImportDocumentItem> importDocumentItems;
}
#Entity
public class ImportDocumentItem {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "import_document_id")
#JsonIgnore
private ImportDocument importDocument;
}
I have implemented JpaRepository interfaces for both domain classes.
I try to save with:
importDocumentRepository.save(importDocument);
When I save ImportDocument object, everything is inserted. But the problem is that, the import_document_item.import_document_id (which is foreign key of import_document_id) attribute is filled with null value, not with id of import_document that I expected. How can I fix this issue?
Thanks a lot.
You have to set entity relations on both side before saving. Here an example
ImportDocument importDocument = new ImportDocument();
//...
importDocument.setImportDocumentItems(items);
items.forEach(ImportDocumentItem::setImportDocument);
importDocumentRepository.save(importDocument);

JPA dataIntegrityViolationException occurs for multiple parents

I am working on simple spring security demo and want to put user and role info into db. Here is the simple structure of my entity.
#Entity
#Table(name = "users")
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private Long userId;
#OneToMany(mappedBy = "users", fetch = FetchType.LAZY, orphanRemoval=true, cascade = CascadeType.ALL)
private List<UserRoleMapping> userRoleMapping;
}
//
#Entity
#Table(name = "user_role_mapping")
public class UserRoleMapping {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_role_mapping_id")
private Long userRoleMappingId;
#ManyToOne(fetch = FetchType.LAZY)
private Users users;
#ManyToOne(fetch = FetchType.LAZY)
private UserRole userRole;
}
//
#Entity
#Table(name = "users_role")
public class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id")
private Long roleId;
#Column(name = "role")
private String role;
#Column(name = "role_desc")
private String roleDesc;
#OneToMany(mappedBy = "userRole", fetch = FetchType.LAZY, orphanRemoval=true)
private List<UserRoleMapping> userRoleMapping;
}
In my use case, I have to make sure when the user is created then I have to insert subsequence userRoleMapping. And If the userRole is removed then the userRoleMapping must be deleted as well.
So I put CascadeType.ALL and orphanRemoval=true in users entity, and orphanRemoval=true in userRole entity.
However, when I run userRoleRepository.delete(userRole). I have dataIntegrityViolationException.
I did some researches on it and understand it is a kind of jpa constrains to make sure we delete the parents (users) as well.
May I ask if there are any workaround for my use case?
Thanks
Here is the solution to my use cases. Instead of using OneToMany in both entity, I should use ManyToMany relationship. And it is quite make sense as I don't care (for now) the mapping in java logic. Here is my code
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private Long userId;
#ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
#JoinTable
private Set<UserRole> userRole;
}
//
public class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id")
private Long roleId;
#Column(name = "role")
private String role;
#Column(name = "role_desc")
private String roleDesc;
#OneToMany(mappedBy = "userRole", fetch = FetchType.LAZY)
private Set<Users> users;
}

JPA two Entities one Relationship: How do I obtain a Set of an entity that is linked through a relationship?

I have three tables each mapping to one of these entities. The 'assigned' table acts as the relationship between 'users' and 'roles' with a foreign key to each table. How would I map this on my entities so that I can get a Set of EntityRoles from the UserEntity? I can't quite figure out how to make this work. Is this even possible?
#Entity
#Table(name = "users")
public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="user_id")
private long id;
#Column(name="user_username")
private String username;
#Column(name="user_password")
private String password;
#Column(name="user_email")
private String email;
//I want to be able to get a set of RoleEntities
#OneToMany(fetch = FetchType.LAZY, mappedBy = "id")
private Set<RoleEntity> roles;
}
#Entity
#Table(name = "assigned")
public class AssignedEntity implements Serializable {
#Id
//#Column(name = "assigned_role")
#ManyToOne(targetEntity = RoleEntity.class, fetch = FetchType.LAZY)
#JoinColumn(name = "fk_role")
private long roleId;
#Id
//#Column(name = "assigned_user")
#ManyToOne(targetEntity = UserEntity.class, fetch = FetchType.LAZY)
#JoinColumn(name = "fk_user")
private long userId;
}
#Entity
#Table(name = "roles")
public class RoleEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="role_id")
#OneToOne(fetch = FetchType.LAZY, mappedBy="roleId")
private long id;
#Column(name="role_name")
private String name;
}
You are using an incorrect/inconvenient mapping. Always keep things as simply as possible.
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue
private Long id;
#ManyToMany(fetch = FetchType.LAZY)
private List<Role> roles;
}
#Entity
#Table(name = "roles")
public class Role {
#Id
private Long id;
#Column
private String name;
}
A persistent provider will create a (valid) join table for you. You can specify the name of the join table using #JoinTable annotation. Also you will need to think about auto generation values of id for the Role entity: the roles table is something like a reference data table. So, probably, you will need to hardcode the id values.
To get user roles (in the persistent context):
user.getRoles()

Spring data : issue with OneToOne relationship

I am developping a webapp (Spring J2EE/angularjs)
I want to set a relationship between two entities :
citizen (id, lastName, city)
city (id, cityName)
A citizen live in only one city.
I need to find a city from a citizen.
I don't need to find a citizen from a city.
I have done that :
#Entity
#Table(name = "citizen")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Citizen implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "last_name")
private String lastName;
#OneToOne
private City city;
}
#Entity
#Table(name = "city")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class City implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "city_name")
private String cityName;
}
In database I have inserted data. Citizen 1, 2 and 3 are linked to City 1
and Citizen 4 is linked to City 2
When I try to load all citizen, I am getting the error:
More than one row with the given identifier was found: 1, for class: com.myApp.rh.domain.Citizen
What's wrong in my entities?
Thanks
It seems that you are missing the #JoinColumn annotation in your Citizen entity.
#Entity
#Table(name = "citizen")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Citizen implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "last_name")
private String lastName;
#OneToOne
#JoinColumn(name = "id", unique = true)
private City city;
}
#Entity
#Table(name = "city")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class City implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "city_name")
private String cityName;
}

Hashmap with 2 Foreign Keys

How to create a hashmap with 2 foreign keys as reference? Something like, Table 3 have a hashmap that for each table1 id have an id from table2.
#Entity
public class table1 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
#Entity
public class table2 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
I was trying something like this:
#Entity
public class table3 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;
#ElementCollection
#MapKeyJoinColumn(name = "table1", referencedColumnName = "ID")
#MapKeyJoinColumn(name = "table2", referencedColumnName = "ID")
private Map<table1, table2> hashmap_relation = new LinkedHashMap<table1, table2>();
...