BAEL-5118 (#11238)
* BAEL-5118 How to solve Hibernate “object references an unsaved transient instance” error * BAEL-5118 How to solve Hibernate “object references an unsaved transient instance” error - refactoring
This commit is contained in:
parent
a5bcd85b16
commit
5cb50132f7
@ -0,0 +1,51 @@
|
||||
package com.baeldung.hibernate.exception.transientobject;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Address;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Department;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Author;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Book;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Employee;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.User;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
public class HibernateUtil {
|
||||
private static SessionFactory sessionFactory;
|
||||
|
||||
public static SessionFactory getSessionFactory() {
|
||||
if (sessionFactory == null) {
|
||||
try {
|
||||
Configuration configuration = new Configuration();
|
||||
Properties settings = new Properties();
|
||||
settings.put(Environment.DRIVER, "org.hsqldb.jdbcDriver");
|
||||
settings.put(Environment.URL, "jdbc:hsqldb:mem:transient");
|
||||
settings.put(Environment.USER, "sa");
|
||||
settings.put(Environment.PASS, "");
|
||||
settings.put(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect");
|
||||
settings.put(Environment.SHOW_SQL, "true");
|
||||
settings.put(Environment.USE_SQL_COMMENTS, "true");
|
||||
settings.put(Environment.HBM2DDL_AUTO, "update");
|
||||
configuration.setProperties(settings);
|
||||
configuration.addAnnotatedClass(User.class);
|
||||
configuration.addAnnotatedClass(Address.class);
|
||||
configuration.addAnnotatedClass(Department.class);
|
||||
configuration.addAnnotatedClass(Employee.class);
|
||||
configuration.addAnnotatedClass(Book.class);
|
||||
configuration.addAnnotatedClass(Author.class);
|
||||
|
||||
|
||||
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
|
||||
.applySettings(configuration.getProperties()).build();
|
||||
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return sessionFactory;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.baeldung.hibernate.exception.transientobject.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "address")
|
||||
public class Address {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "city")
|
||||
private String city;
|
||||
|
||||
@Column(name = "street")
|
||||
private String street;
|
||||
|
||||
@OneToOne(mappedBy = "address")
|
||||
private User user;
|
||||
|
||||
public Address() {
|
||||
}
|
||||
|
||||
public Address(String city, String street) {
|
||||
this.city = city;
|
||||
this.street = street;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.baeldung.hibernate.exception.transientobject.entity;
|
||||
|
||||
import org.hibernate.annotations.Cascade;
|
||||
import org.hibernate.annotations.CascadeType;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "author")
|
||||
public class Author {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private int id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@ManyToMany
|
||||
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST})
|
||||
@JoinColumn(name = "book_id")
|
||||
private Set<Book> books = new HashSet<>();
|
||||
|
||||
public void addBook(Book book) {
|
||||
books.add(book);
|
||||
}
|
||||
|
||||
// standard getters and setters
|
||||
|
||||
public Author() {
|
||||
}
|
||||
|
||||
public Author(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Set<Book> getBooks() {
|
||||
return books;
|
||||
}
|
||||
|
||||
public void setBooks(Set<Book> books) {
|
||||
this.books = books;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package com.baeldung.hibernate.exception.transientobject.entity;
|
||||
|
||||
|
||||
import org.hibernate.annotations.Cascade;
|
||||
import org.hibernate.annotations.CascadeType;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "book")
|
||||
public class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private int id;
|
||||
|
||||
@Column(name = "title")
|
||||
private String title;
|
||||
|
||||
@ManyToMany
|
||||
@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.PERSIST})
|
||||
@JoinColumn(name = "author_id")
|
||||
private Set<Author> authors = new HashSet<>();
|
||||
|
||||
public void addAuthor(Author author) {
|
||||
authors.add(author);
|
||||
}
|
||||
|
||||
// standard getters and setters
|
||||
|
||||
public Book() {
|
||||
}
|
||||
|
||||
public Book(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Set<Author> getAuthors() {
|
||||
return authors;
|
||||
}
|
||||
|
||||
public void setAuthors(Set<Author> authors) {
|
||||
this.authors = authors;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package com.baeldung.hibernate.exception.transientobject.entity;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "department")
|
||||
public class Department {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private int id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
private Set<Employee> employees = new HashSet<>();
|
||||
|
||||
public void addEmployee(Employee employee) {
|
||||
employees.add(employee);
|
||||
}
|
||||
|
||||
// standard getters and setters
|
||||
|
||||
public Department() {
|
||||
}
|
||||
|
||||
public Department(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Department(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Set<Employee> getEmployees() {
|
||||
return employees;
|
||||
}
|
||||
|
||||
public void setEmployees(Set<Employee> employees) {
|
||||
this.employees = employees;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.baeldung.hibernate.exception.transientobject.entity;
|
||||
|
||||
|
||||
import org.hibernate.annotations.Cascade;
|
||||
import org.hibernate.annotations.CascadeType;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "employee")
|
||||
public class Employee {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private int id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@ManyToOne
|
||||
@Cascade(CascadeType.SAVE_UPDATE)
|
||||
@JoinColumn(name = "department_id")
|
||||
private Department department;
|
||||
|
||||
// standard getters and setters
|
||||
|
||||
public Employee() {
|
||||
}
|
||||
|
||||
public Employee(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Department getDepartment() {
|
||||
return department;
|
||||
}
|
||||
|
||||
public void setDepartment(Department department) {
|
||||
this.department = department;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.baeldung.hibernate.exception.transientobject.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "user")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private int id;
|
||||
|
||||
@Column(name = "first_name")
|
||||
private String firstName;
|
||||
|
||||
@Column(name = "last_name")
|
||||
private String lastName;
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "address_id", referencedColumnName = "id")
|
||||
private Address address;
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
public User(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int 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 Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package com.baeldung.hibernate.exception.transientobject;
|
||||
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Address;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Department;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Author;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Book;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.Employee;
|
||||
import com.baeldung.hibernate.exception.transientobject.entity.User;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
public class HibernateTransientObjectUnitTest {
|
||||
|
||||
private static SessionFactory sessionFactory;
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
sessionFactory = HibernateUtil.getSessionFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSaveEntitiesWithOneToOneAssociation_thenSuccess() {
|
||||
User user = new User("Bob", "Smith");
|
||||
Address address = new Address("London", "221b Baker Street");
|
||||
user.setAddress(address);
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save(user);
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSaveEntitiesWithOneToManyAssociation_thenSuccess() {
|
||||
Department department = new Department();
|
||||
department.setName("IT Support");
|
||||
Employee employee = new Employee("John Doe");
|
||||
employee.setDepartment(department);
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save(employee);
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSaveEntitiesWithManyToManyAssociation_thenSuccess_1() {
|
||||
Book book = new Book("Design Patterns: Elements of Reusable Object-Oriented Software");
|
||||
book.addAuthor(new Author("Erich Gamma"));
|
||||
book.addAuthor(new Author("John Vlissides"));
|
||||
book.addAuthor(new Author("Richard Helm"));
|
||||
book.addAuthor(new Author("Ralph Johnson"));
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save(book);
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSaveEntitiesWithManyToManyAssociation_thenSuccess_2() {
|
||||
Author author = new Author("Erich Gamma");
|
||||
author.addBook(new Book("Design Patterns: Elements of Reusable Object-Oriented Software"));
|
||||
author.addBook(new Book("Introduction to Object Orient Design in C"));
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save(author);
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user