Reference Column throwing error in Hibernate - spring

User entity has OneToMany mapping with UserRole entity i.e 1 user can have many Role ids .
I am getting the below error : -
Caused by: org.hibernate.cfg.RecoverableException: Unable to find
column with logical name: USER_ID in
org.hibernate.mapping.Table(t_users) and its related supertables and
secondary tables
#Entity
#Table(name="T_USERS")
public class User {
#Column(name="ID_COL")
#Id
#SequenceGenerator(name="s")
private Integer userId;
#Column(name="USER_NAME ")
private String userName;
#Column(name="USER_EMAIL")
private String userEmail;
#Column(name="PASSWORD")
private String password;
#Column(name="IS_ACTIVE")
private Integer isActive;
#OneToMany
#JoinColumns(
{
#JoinColumn(updatable=false,insertable=false, name="ID_COL", referencedColumnName="USER_ID"),
}
)
private List<UserRole> userRole ;
// removed getters n setters for brevity
}
#Entity
#Table(name="T_MAP_USER_ROLES")
public class UserRole {
#Column(name="MAP_ID")
#Id
#SequenceGenerator(name="seq_user_role")
private Integer mapId;
#Column(name="USER_ID")
private Integer userId;
#Column(name="ROLE_ID ")
private Integer roleId;
#Column(name="IS_ACTIVE")
private Integer isActive;
#OneToOne
#JoinColumns(
{
#JoinColumn(updatable=false,insertable=false, name="ROLE_ID", referencedColumnName="ROLE_ID"),
}
)
private Role role;
What is the cause of the issue and how can I resolve it?
the mapping between UserRole and Role entity is working fine

#JoinColumns is only used for composite foreign keys. In this case, you just need #JoinColumn:
#OneToMany #JoinColumn(updatable=false,insertable=false, name="ID_COL")
Also, please note that you don't need "referencedColumnName" for single column foreign keys.

Related

Spring data jpa hibernate one to may duplicate issue

I have one to many relation ship between a User and UserRole.
public class User {
#Id
#GeneratedValue
private long id;
#Column(unique = true)
private String username;
private String password;
#OneToMany(fetch=FetchType.EAGER)
#JoinTable(
name = "user_roles",
joinColumns = {#JoinColumn(name="userId")},
inverseJoinColumns = {#JoinColumn(name="roleId")}
)
private Collection<UserRole> roles;
}
and
public class UserRole {
#Id
#GeneratedValue
private long id;
#Column(unique = true)
private String roleName;
}
I am able to save a user at first. But when I try to save another user it rejects with an exception of duplicated entry on the junction table
One thing I noticed is when we have One-to-Many association the many side foreign key will be a primary key on the junction table. So, I need to make the relation Many-to-Many. So that the combination of both foreign keys will serve as a composite key.

OneToMany relationship using non-primary composite key

I have a table structure like this
Good Assignments Entity
#Embeddable
public class GoodAssignmentId {
String clientId,
String assignmentNumber;
LocalDate effectiveDate;
// Getters and setters
}
#Entity
#IdClass(GoodAssignmentId.class)
class GoodAssignment {
#id
String clientId;
#Id
String assignmentNumber;
#Id
LocalDate effectiveDate;
#OneToMany(mappedBy = "parentKey")
Set<GoodTasks> children;
String description;
// getters and setters goes below
}
Bad Assignments Entity
#Entity
#IdClass(BadAssignmentId.class)
class BadAssignment {
#id
String clientId;
#Id
String assignementNumber;
#Id
LocalDate effectiveDate;
String description;
// Getters and setters goes below
}
Child entities
#Entity
#IdClass(ParentTasksId.class)
#DiscriminatorColumn(name = "fieldD", discriminatorType = DiscriminatorType.STRING)
class ParentTasks {
#Id
String clientId;
#Id
String assignmentNumber;
#Id
String taskNumber;
}
#Entity
#DiscriminatorValue("G")
class GoodTasks extends ParentTasks {
#ManyToOne
#JoinColumns({
#JoinColumn(name = "clientId", referencedColumName = "clientId"),
#JoinColumn(name = "assignmentNumber", referencedColumName = "assignmentNumber")
})
GoodAssignments parentKey;
other fields....
}
This shows the error referencedColumnNames(fieldA, fieldB) of .... not mapped to a single property.
Unfortunately I cannot change the table structure. TableA has 3 columns as primary key, but only two of them forms the primary key in table B along with another field (fieldD via #DiscriminatorValue used by multiple classes). How can I map this relationship to get list of TableB items in TableA?
Example Class Diagram:
Effective date in the assignments tables is not part of tasks. So this is not a perfect relationship in JPA terms. It's a legacy design which cannot be changed for some reasons.

JPA ManyToMany Inserting duplicate values

I have the following model:
#Entity
#Table(name="`tbUser`")
public class User {
#Id
#SequenceGenerator(name="tbuser_id_seq",
sequenceName="tbuser_id_seq",
allocationSize=1)
#Column(name="`userId`")
#GeneratedValue
private Long id;
#Column(name="username")
private String username;
#Column(name="password")
private String password;
#Column(name="nombres")
private String firstName;
#Column(name="apellidos")
private String lastName;
#Column(name="email")
private String email;
#Column(name="`avatarUrl`")
private String avatarUrl;
#ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.MERGE)
#JoinTable(name="`tbUserRole`",
joinColumns=#JoinColumn(name="`userId`",referencedColumnName="`userId`"),
inverseJoinColumns=#JoinColumn(name="`roleId`",referencedColumnName="`roleId`"))
private List<Role> roles = new ArrayList<>();
...
#Entity
#Table(name="`tbRole`")
public class Role {
#Id
#Column(name="`roleId`")
#GeneratedValue
private Long id;
#Column(name="name")
String name;
#ManyToMany(mappedBy="roles")
private List<User> users = new ArrayList<>();
...
Which is mapped to the following tables:
I tried to insert a user with an existing role in the following two ways:
user.getRoles().add(role) and repository.save(new User())
either way, the role is inserted again in the database.
e.g
If these are the existing Roles in the DB:
ID Name
1 ADMIN
2 USER
and I insert a user with an ADMIN role, it is inserted again:
ID Name
1 ADMIN
2 USER
3 ADMIN
How can I resolve this?
I've already tried the solution in this post, but did not work.
The name of the role is not the identifier of the entity nor is it unique. So, the id of the role object will be null if you do something like :
Role role = new Role();
role.setName("ADMIN");
user.getRoles().add(role);
repository.save(user);
JPA will then assume that you passed a new object and will generate a new id for it based on the #GeneratedValue annotation.
Assuming that you use Spring Data you will need to do something like:
Role role = roleRepository.findByName("ADMIN");
user.getRoles().add(role);

Usual field as foreign key

I have two tables. I want to make between them relationship, but the thing is that the child table connects to an attribute in a parent node, which is not a PK. How can I assign a non-PK field as a FK for a table?
Here are the tables. User Information:
#Entity
#Table(name="user")
public class userinformation implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="USER_ID")
private int uID;
#Column(name="LIB_ID")
private String libID;
//Other attributes
}
Lib Information
#Entity
#Table(name="libinfo")
public class Auth {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="AUTH_ID")
private int authID;
#Column(name="LIB_ID")
private String lib_ID;
//Other attributes
}
They both should be linked through libID (surely unique). Any idea how to implement it correctly?
Given:
class User {
#Column(name = "lib_id")
private String libID;
}
you must map the Auth entity as:
class Auth {
#JoinColumn(name = "lib_id", referencedColumnName = "lib_id")
#ManyToOne
private User user;
}
Basically, referencedColumnName is used to inform the JPA provider that it should use a column other than the primary key column of the referenced entity (which is used by default with #ManyToOne mappings).

Spring and Hibernate Error -- not-null property references a null or transient value: com.tharaka.model.Employee.designation

im new to Spring and hibernate, i got the error above when trying to persist the transaction data. please try to help this problem
Here's my Entity:
#Entity #NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e")
public class Employee implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String city;
private String civil;
#Temporal(TemporalType.DATE)
#Column(name="dob", length=11)
private Date dob;
private String email;
private int epf;
private String fname;
private String gender;
private int landtp;
private String lname;
#Temporal(TemporalType.DATE)
#Column(name="salaryincrement", length=11)
//bi-directional many-to-one association to Designation
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="designation_id", nullable=false)
private Designation designation;
public Employee() { }
#Entity
#NamedQuery(name="Designation.findAll", query="SELECT d FROM Designation d")
public class Designation implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String type;
//bi-directional many-to-one association to Employee
#OneToMany(mappedBy="designation")//, cascade=CascadeType.ALL
private List<Employee> employees;
public Designation() {
}
this is my Entity class,
Entities have a getters ans setters
designation is set nullable = false. However employees variable isn't initialized in Designation. So, you'll have to initialize as
#OneToMany(mappedBy="designation")//, cascade=CascadeType.ALL
private List<Employee> employees = new LinkedList<>();
I'm not sure that you can go with primitive type int as your Id - you should probably use Integer - because int has default zero value and cannot be null, your new record can be rather seen as a detached entity with Id ZERO and not as a transient one.
The same mistake is in Designation class.
See Primitive or wrapper for hibernate primary keys

Resources