I have an Entity which contains a collection of another Entity which itself references the same class in a collection, with the following mappings:
#Entity
#Table(name="parents")
public class Parent {
#Id
#GeneratedValue
private long id;
#ElementCollection
#Cascade(org.hibernate.annotations.CascadeType.ALL)
private Set<Child> children;
public Parent() {}
public Parent(Set<Child> children) {
this.children = children;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
#Entity
#Table(name="children")
public static class Child {
#Id
#GeneratedValue
private long id;
private String name;
#ElementCollection
#Cascade(org.hibernate.annotations.CascadeType.ALL)
private Set<Child> dependencies;
public Child() {}
public Child(String name) {
this.name = name;
dependencies = new LinkedHashSet<>();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public getDependencies() {
return dependencies;
}
public setDependencies(Set<Child> dependencies) {
this.dependencies = dependencies;
}
}
}
But when I try to save it, I get a: java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing exception
I've read in another post that I should use #Cascade(CascadeType.ALL) annotation, but as you can see, I tried doing so and it didn't solve my problem.
Please help me understand what's wrong with these mappings
Related
I have an Entity which contains another Entity in a collection, which itself contains a collection of entities of the same class, like so:
#Entity
#Table(name="parents")
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#OneToMany(cascade = CascadeType.ALL)
private Set<Task> tasks;
public Parent() {}
public Parent(Set<Task> tasks) {
this.tasks = tasks;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Set<Task> getTasks() {
return tasks;
}
public void setTasks(Set<Task> tasks) {
this.tasks = tasks;
}
#Entity
#Table(name="tasks")
public static class Task {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "task_id")
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL)
private Set<Task> dependencies;
public Task() {}
public Task(String name) {
this.name = name;
dependencies = new LinkedHashSet<>();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Task> getDependencies() {
return dependencies;
}
public void setDependencies(Set<Task> dependencies) {
this.dependencies = dependencies;
}
}
}
The problem in my case is that two Task may reference the same Task in their dependencies, and so when I try to save my Parent, I get a org.hibernate.exception.ConstraintViolationException: could not execute statement and SQL says: Duplicate entry '12' for key 'UK_q8xuxyx9iylvc9ddh8fudtlsf'
How can I overcome this issue ? Any help is appreciated.
foreign key is not saving into the task table association is not forming while saving the holder through the rest api.
Please let me known what i am missing here
REST API
URL : localhost:8080/priority/holder
PAYLOAD :
{
"name": "Madhu",
"task": [
{
"name": "update",
"type": "Technical"
},
{
"name": "jogg",
"type": "fitness"
},
{
"name": "work",
"type": "project"
}
]
}
Here i am adding my controller,entities and service images
[Controller][1]
#RestController
#RequestMapping(value = "/priority")
public class TaskController {
#Autowired
TaskService taskService;
#PostMapping(value = "/holder")
public Holder createHolder(#RequestBody Holder holder) {
return taskService.createHolder(holder);
}
}
#Service
public class TaskService {
#Autowired
TaskRepositriy taskRepo;
#Autowired
HolderRepositry holderRepo;
public Holder createHolder(Holder holder) {
return holderRepo.save(holder);
}
}
#Entity
public class Holder {
#Id
#GeneratedValue
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "holder",fetch=FetchType.LAZY)
private List<Task> task;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Task> getTask() {
return task;
}
public void setTask(List<Task> task) {
this.task = task;
}
}
#Entity
public class Task {
#Id
#GeneratedValue
private long id;
private String name;
#ManyToOne
#JoinColumn(name="holder_task")
private Holder holder;
public Holder getHolder() {
return holder;
}
public void setHolder(Holder holder) {
this.holder = holder;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I have two entities. Student and department.One department has many student. I have specified fetch type lazy. still when I am trying to fetch only department entity it is showing student data as well.
#Entity(name = "tbl_department")
public class DepartmentEntity implements Serializable {
private static final long serialVersionUID = 1560990434803170482L;
#Id
#GeneratedValue
private Integer id;
#NotNull(message = "Department name can not be null")
private String departmentName;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "department", fetch = FetchType.LAZY)
private Set<StudentEntity> studentList;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public Set<StudentEntity> getStudentList() {
return studentList;
}
public void setStudentList(Set<StudentEntity> studentList) {
this.studentList = studentList;
}
#Entity(name = "tbl_student")
public class StudentEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2969421115938100526L;
#Id
#GeneratedValue
private Integer id;
#NotNull(message = "First Name Can not null")
private String firstName;
#NotNull(message = "Last Name Can not null")
private String lastName;
#NotNull(message = "Date Of Birth Can not null")
private Date dateOfBirth;
private Integer age;
#NotNull(message = "Address Can not null")
private String address;
#JsonIgnore
#ManyToOne(cascade = CascadeType.ALL)
private DepartmentEntity department;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public DepartmentEntity getDepartment() {
return department;
}
public void setDepartment(DepartmentEntity department) {
this.department = department;
}
So when I am trying to fetch department entity using departmentRepo it shows all students mapped to that department even if I specified fetch type lazy
Can you declare your entities as below and try once
Student Entity:
#OrderBy("id ASC")
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="departmentid")
#JsonIgnore
private Department department;
Department Entity:
#OrderBy("id ASC")
#OneToMany(fetch=FetchType.LAZY, mappedBy="department")
private Set<Student> students = new LinkedHashSet<Student>(0);
I have two simple tables: Users and User_Roles.
In both tables i have a field email and i want load User_Roles from UserEntity, the query should be:
SELECT *
FROM Users u, User_Roles ur
WHERE u.email = ur.email;
When i try to "link" the email field i get the error "Repeated column in mapping for entity: UserEntity column: email".
I've tried to add any kind of combination (mappedBy, refColumn etc) but the error is even the same...
User
#Entity
#Table(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String email;
private UserRolesEntity roles;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Basic
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#OneToOne
#JoinColumn(name = "email")
public UserRolesEntity getRoles() {
return roles;
}
public void setRoles(UserRolesEntity roles) {
this.roles = roles;
}
}
User_Roles
#Entity
#Table(name = "user_roles")
public class UserRolesEntity {
private long id;
private String email;
private String role;
#Id
#Column(name = "user_role_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Basic
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Basic
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
If you want to link the User_Roles and User, you should keep the User's primary key in User_Roles. So you would better modify your User_Roles table like this:
long user_role_id
long user
String role
Then your User_Roles class would be:
#Entity
#Table(name = "user_roles")
public class UserRolesEntity {
private long id;
private User user;
private String role;
#Id
#Column(name = "user_role_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#OneToOne
public User getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
#Basic
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
If you want get the user email from user_role, you can do like this: userRole.getUser().getEmail()
And then the User class would be:
#Entity
#Table(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String email;
private UserRolesEntity roles;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Basic
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#OneToOne(mappedBy="user")
public UserRolesEntity getRoles() {
return roles;
}
public void setRoles(UserRolesEntity roles) {
this.roles = roles;
}
}
I'm having error in main can anyone help me find where the bug is ? I'm trying to create a class and use setter/getter to set each field where eventually I will test this class it to make sure the fields work
public class College{
public class person{
private String name;
private int age;
private double id;
//constructor to set fields
public Schedule (String name, int age, double id){
this.name= name;
this.age= age;
this.id= id;
}
public String getName(){
return this.name;
}
public void setName(String Name) {
this.name= name;
}
public int getAge(){
return this.Age;
}
public void setAge(int age) {
this.age = age;
}
public double getId(){
return this.id;
}
public void setId(double id) {
this.id = id;
}
}
public static void main(String[] args) {
Schedule Per1= new College("John", 2,2.0);
}
}
I think you might want to read about how to create class properly.
The link below would help you (in C#):
http://msdn.microsoft.com/en-us/library/x9afc042.aspx
public class person{
private String name;
private int age;
private double id;
//constructor to set fields
public person(String name, int age, double id){
this.name= name;
this.age= age;
this.id= id;
}
public String getName(){
return this.name;
}
public void setName(String Name) {
this.name= name;
}
public int getAge(){
return this.Age;
}
public void setAge(int age) {
this.age = age;
}
public double getId(){
return this.id;
}
public void setId(double id) {
this.id = id;
}
}
public static void main(String[] args) {
person Per1= new person("John", 2,2.0);
}