diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/HibernateUtil.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/HibernateUtil.java new file mode 100644 index 0000000000..a40279661f --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/HibernateUtil.java @@ -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; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Address.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Address.java new file mode 100644 index 0000000000..e450fc3c18 --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Address.java @@ -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; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Author.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Author.java new file mode 100644 index 0000000000..f1a88daa36 --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Author.java @@ -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 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 getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } +} diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Book.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Book.java new file mode 100644 index 0000000000..91728430ea --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Book.java @@ -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 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 getAuthors() { + return authors; + } + + public void setAuthors(Set authors) { + this.authors = authors; + } +} diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Department.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Department.java new file mode 100644 index 0000000000..4b8fa69964 --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Department.java @@ -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 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 getEmployees() { + return employees; + } + + public void setEmployees(Set employees) { + this.employees = employees; + } +} diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Employee.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Employee.java new file mode 100644 index 0000000000..56443cce70 --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/Employee.java @@ -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; + } +} diff --git a/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/User.java b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/User.java new file mode 100644 index 0000000000..eff1a88b51 --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/main/java/com/baeldung/hibernate/exception/transientobject/entity/User.java @@ -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; + } +} diff --git a/persistence-modules/hibernate-exceptions/src/test/java/com/baeldung/hibernate/exception/transientobject/HibernateTransientObjectUnitTest.java b/persistence-modules/hibernate-exceptions/src/test/java/com/baeldung/hibernate/exception/transientobject/HibernateTransientObjectUnitTest.java new file mode 100644 index 0000000000..3f6d0effa9 --- /dev/null +++ b/persistence-modules/hibernate-exceptions/src/test/java/com/baeldung/hibernate/exception/transientobject/HibernateTransientObjectUnitTest.java @@ -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(); + } +}