Hashmap with 2 Foreign Keys - jpa

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>();
...

Related

JPA Composite Key: Avoid Unnecessary of Table Creation

I am learning JPA.
I need to create 3 tables, product (pk => id), cart (pk => id), cart_details (pk also fk => product_id, cart_id).
The relation is : One cart can contain multiple cart_details, one cart_details can contain multiple product and one product can be put on multiple cart_details. I need only 3 tables, but JPA creates 4 tables for me: product, cart, cart_details, cart_details_product
#Entity
#Table(name = "product")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#NotBlank
#Size(max = 50)
private String name;
#Size(max = 300)
private String description;
#NotNull
private Double price;
private int qty;
#Column(name = "created_date")
private Date createdDate;
#Column(name = "updated_date")
private Date updatedDate;
}
#Entity
#Table(name = "cart")
public class Cart implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "total_price")
private double totalPrice;
#Column(name = "created_date")
private Date createdDate;
#Column(name = "updated_date")
private Date updatedDate;
}
#Entity
#Table(name = "cart_details")
public class CartDetails implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private CartDetailsId id;
#MapsId("cartId")
#ManyToOne
#JoinColumn(name = "cart_id", referencedColumnName = "id", insertable = false, updatable = false)
private Cart cart;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "product_id", referencedColumnName = "id")
private Set<Product> product;
private int quantity;
private double price;
}
#Embeddable
public class CartDetailsId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "cart_id")
private Long cartId;
#Column(name = "product_id")
private Long productId;
}
How to avoid creation of this table (cart_details_product)? I think i don't need this table.

JPA Entity mapping for join columns

I have three tables EmployeeDepartment, EmployeeGroup and EmpplyeeDetails Table. EmployeeDepartment table has primary key departmentId and a column groupId, EmployeeGroupTable has primary key groupid which should be generated from databse sequence GroupIdGenerator.
EmployeeDetails have two primary keys as groupid and employeeid. Groupid should be same as of the previous table
These values in all table should insert in one transaction.
Can you help me with correct JAP Entity mapping?
I already tried with different combination of Generated value and Sequence generator but not able to save the data into table.
#Entity
#Table(name="EMPLOYEE_DEPARTMENT")
public class EmployeeDepartment {
#Column(name = "DEPARTMENT_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"departmentid-gen")
#Id
#NotNull
#SequenceGenerator(name = "departmentid-gen", sequenceName =
"DEAPARTMENT_ID_GENERATOR" )
private long departmentId;
#OneToOne(mappedBy = "employeeGroup")
private EmployeeGroup employeeGroup;
}
#Coulmn(name="GROUP_ID")
private long groupId;
#Entity
#Table(name="EMPLOYEE_GROUP")
public class EmployeeGroup {
#Column(name = "GROUP_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"groupid-gen")
#Id
#NotNull
#SequenceGenerator(name = "groupid-gen", sequenceName =
"GROUIP_ID_GENERATOR" )
private long groupId;
#OneToMany(mappedBy = "employeeDetail")
private List<EmployeeDetail> employeeDetails;
#OneToOne
#JoinColumn(name = "DEPARTMENT_ID", insertable=false ,
updatable=false)
private EmployeeDepartment employeeDepatment;
}
#Entity
#Table(name = "EMPLOYEE_DETAIL")
#IdClass(EmployeeID.class)
public class EmployeeDetail {
#ManyToOne
#JoinColumn(name = "GROUP_ID", insertable=false , updatable=false)
private EmployeeGroup employeeGroup;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"groupid-gen")
#SequenceGenerator(name = "groupid-gen", sequenceName =
"GROUIP_ID_GENERATOR" )
#Column(name = "GROUP_ID")
#Nonnull
private Long groupId;
#Id
#Nonnull
#Column(name = "EMPLOYEE_ID")
private Long employeeId;
}
public class EmployeeId{
private Long groupId;
private Long employeeId;
public EmployeeId(final Long groupId, final Long employeeId) {
this.groupId = groupId;
this.employeeId = employeeId;
}
public EmployeeId() {
}
}
Expected result in these 3 tables should have proper values like.
Table EmployeeDepartment
DepartmentID GroupId
1 1
Table EmployeeGroup
GroupID
1
Table EmployeeDetail
GroupId EmployeeId
1 1
1 2
1 3
Actual results are below
Table EmployeeDepartment
DepartmentID GroupId
1 0
Table EmployeeGroup
GroupID
1
Table EmployeeDetail
GroupId EmployeeId
2 1
3 2
4 3
The important annotation is #MapsId("groupId")
Your mapping should be something like this:
#Entity
#Table(name="EMPLOYEE_DEPARTMENT")
public class EmployeeDepartment {
#Column(name = "DEPARTMENT_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"departmentid-gen")
#Id
#NotNull
#SequenceGenerator(name = "departmentid-gen", sequenceName =
"DEAPARTMENT_ID_GENERATOR" )
private long departmentId;
#OneToOne(mappedBy = "employeeGroup")
private EmployeeGroup employeeGroup;
#Column(name="GROUP_ID")
private long groupId;
#Entity
#Table(name="EMPLOYEE_GROUP")
public class EmployeeGroup {
#Column(name = "GROUP_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"groupid-gen")
#Id
#NotNull
#SequenceGenerator(name = "groupid-gen", sequenceName =
"GROUIP_ID_GENERATOR" )
private long groupId;
#OneToMany(mappedBy = "employeeDetail")
private List<EmployeeDetail> employeeDetails;
#OneToOne
#JoinColumn(name = "DEPARTMENT_ID", insertable=false, updatable=false)
private EmployeeDepartment employeeDepatment;
#Entity
#Table(name = "EMPLOYEE_DETAIL")
#IdClass(EmployeeID.class)
public class EmployeeDetail {
#MapsId("groupId")
#ManyToOne
#JoinColumn(name = "GROUP_ID", insertable=false , updatable=false)
private EmployeeGroup employeeGroup;
#Id
#Nonnull
#Column(name = "EMPLOYEE_ID")
private Long employeeId;
#Entity
#Table(name="EMPLOYEE_DEPARTMENT")
public class EmployeeDepartment {
#Column(name = "DEPARTMENT_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"departmentid-gen")
#Id
#NotNull
#SequenceGenerator(name = "departmentid-gen", sequenceName =
"DEAPARTMENT_ID_GENERATOR" )
private Long departmentId;
#OneToOne(mappedBy = "employeeGroup")
private EmployeeGroup employeeGroup;
}
#Column(name="GROUP_ID")
private EmployeeGroup group;
#Entity
#Table(name="EMPLOYEE_GROUP")
public class EmployeeGroup {
#Column(name = "GROUP_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"groupid-gen")
#Id
#NotNull
#SequenceGenerator(name = "groupid-gen", sequenceName =
"GROUIP_ID_GENERATOR" )
private Long groupId;
#OneToMany(mappedBy = "employeeDetail")
private List<EmployeeDetail> employeeDetails;
#OneToOne
#JoinColumn(name = "DEPARTMENT_ID", insertable=false ,
updatable=false)
private EmployeeDepartment employeeDepatment;
}
#Entity
#Table(name = "EMPLOYEE_DETAIL")
#IdClass(EmployeeID.class)
public class EmployeeDetail {
#Id
#ManyToOne
#JoinColumn(name = "GROUP_ID", insertable=false , updatable=false)
private EmployeeGroup employeeGroup;
#Id
#Nonnull
#Column(name = "EMPLOYEE_ID")
private Long employeeId;
You also need to change the EmployeeId accordingly:
public class EmployeeId{
private EmployeeGroup employeeGroup;
private Long employeeId;
public EmployeeId(final EmployeeGroup employeeGroup, final Long employeeId) {
this.employeeGroup= employeeGroup;
this.employeeId = employeeId;
}
However I haven't use composite keys this way before. If it doesn't work, then change EmployeeId to an embeddedId:
#Embeddable
public class EmployeeId implements Serializable{
#ManyToOne(fetch = FetchType.LAZY, optional = false)
private EmployeeGroup employeeGroup;
#Nonnull
#Column(name = "EMPLOYEE_ID")
private Long employeeId;
public EmployeeId(final EmployeeGroup employeeGroup, final Long employeeId) {
this.employeeGroup= employeeGroup;
this.employeeId = employeeId;
}
#Entity
#Table(name = "EMPLOYEE_DETAIL")
public class EmployeeDetail {
#EmbeddedId
private EmployeeId id;
#ManyToOne
#JoinColumn(name = "GROUP_ID", insertable=false , updatable=false)
private EmployeeGroup employeeGroup;
}
If it still doesn't work, then please attach the code snippet where you create the entities.

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 Many-To-Many Duplicates

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?

Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property customer invoice

I am new to spring based project,
I have the requirement to create the entity relationship mapping between orders and invoices with OneToMany, and tried below mappings, but ending up with mapping error,
Could you please point me out to fix this issue.
#Entity
#Table(name="Customers")
public class Customers implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
#Column(name = "CustomerId", nullable = false)
private Long CustomerId;
#OneToMany(cascade=CascadeType.ALL, mappedBy="Customers")
private Set<Orders> Orders = new HashSet<Orders>();
}
#Entity
#Table(name="Orders")
public class Orders implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
#Column(name = "orderId", nullable = false)
private Long orderId;
#JoinColumn(name="CustomerId")
#ManyToOne
private Customers customers;
#OneToOne (optional=false,cascade=CascadeType.ALL, mappedBy="orders",targetEntity=Invoices.class)
private Invoices invoices;
}
#Entity
#Table(name="Invoices")
public class Invoices implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
#Column(name = "invoiceId", nullable = false)
private Long invoiceId;
#OneToOne(optional=false,cascade=CascadeType.ALL, mappedBy="invoices",targetEntity=Orders.class)
private Orders orders;
}
Error message:
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.mycompany.myproject.persist.entity.Orders.Customers in com.mycompany.myproject.persist.entity.Customers.Orders
Probably because Orders has a property 'customers' and not 'Customers' (as specified by the 'mappedBy' attribute).
You should tidy up your class names and fields as below:
#Entity
#Table(name="Customers")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
#Column(name = "CustomerId", nullable = false)
private Long customerId;
#OneToMany(cascade=CascadeType.ALL, mappedBy="customer")
private Set<Order> orders = new HashSet<Order>();
}
#Entity
#Table(name="Orders")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
#Column(name = "orderId", nullable = false)
private Long orderId;
#ManyToOne
#JoinColumn(name="CustomerId")
private Customer customer;
#OneToOne(optional=false, cascade=CascadeType.ALL, mappedBy="order")
private Invoice invoice;
}
#Entity
#Table(name="Invoices")
public class Invoice implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
#Column(name = "invoiceId", nullable = false)
private Long invoiceId;
#OneToOne(optional=false,cascade=CascadeType.ALL)
#JoinColumn(name = "InvoiceId")
private Order order;
}