package mapping.entity.unidirectional.manytoone;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.LazyInitializationException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.TransientObjectException;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HibernateMappingMany2OneTest {
private SessionFactory lazySessionFactory = null;
private SessionFactory eagerSessionFactory = null;
private SessionFactory cascadeSessionFactory = null;
@Before
public void setup() {
Configuration lazyConfig = new Configuration().configure("mapping/entity/unidirectional/manytoone/hibernate.cfg.xml");
lazyConfig.addResource("mapping/entity/unidirectional/manytoone/Customer.hbm-lazy.xml");
lazyConfig.addResource("mapping/entity/unidirectional/manytoone/Address.hbm.xml");
lazySessionFactory = lazyConfig.buildSessionFactory();
Configuration eagerConfig = new Configuration().configure("mapping/entity/unidirectional/manytoone/hibernate.cfg.xml");
eagerConfig.addResource("mapping/entity/unidirectional/manytoone/Customer.hbm-eager.xml");
eagerConfig.addResource("mapping/entity/unidirectional/manytoone/Address.hbm.xml");
eagerSessionFactory = eagerConfig.buildSessionFactory();
Configuration cascadeConfig = new Configuration().configure("mapping/entity/unidirectional/manytoone/hibernate.cfg.xml");
cascadeConfig.addResource("mapping/entity/unidirectional/manytoone/Customer.hbm-cascade.xml");
cascadeConfig.addResource("mapping/entity/unidirectional/manytoone/Address.hbm.xml");
cascadeSessionFactory = cascadeConfig.buildSessionFactory();
}
@After
public void cleanup() {
lazySessionFactory.close();
eagerSessionFactory.close();
cascadeSessionFactory.close();
}
/**
* We are trying to save Customer object without explicitly saving the address object. The method throws TransientObjectException denoting that
* the address object referenced is in a transient state. The issue can be resolved by either saving the address object explicitly or by including
* cascade = "all" property in the Customer.hbm.xml mapping file.
*/
@Test(expected = TransientObjectException.class)
public void testCustomerSave() throws ParseException {
Address address = getAddress("MG Road", "Mysore", "KA", "511001");
Customer c = getCustomer("Gabbar Singh", 'M', "1975-11-30", address);
Session session = null;
Transaction txn = null;
try {
session = lazySessionFactory.openSession();
txn = session.beginTransaction();
session.saveOrUpdate(c);
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
}
/**
* Explicitly saving Address object within the same session. Fires three queries :- 1. Insert query for customer object 2. Insert query for
* address object 3. Update query for updating the customer object with foreign key
*/
@Test
public void testCustomerSaveExplicitAddressSave() throws ParseException {
Address address = getAddress("IG Road", "Bangalore", "KA", "511001");
Customer c = getCustomer("Makkar Singh", 'M', "1985-11-30", address);
Session session = null;
Transaction txn = null;
try {
session = lazySessionFactory.openSession();
txn = session.beginTransaction();
session.saveOrUpdate(c);
session.saveOrUpdate(address); // saving address explicitly
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
}
/**
* Making use of cascade="all" property in Customer.hbm-cascade.xml mapping file
*/
@Test
public void testCustomerSaveCascadeAddressSave() throws ParseException {
Address address = getAddress("RG Road", "Mysore", "KA", "511001");
Customer c = getCustomer("Shakkar Singh", 'M', "1995-11-30", address);
Session session = null;
Transaction txn = null;
try {
session = cascadeSessionFactory.openSession();
txn = session.beginTransaction();
session.saveOrUpdate(c);
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
}
private Customer getCustomer(String name, char gender, String date, Address address) throws ParseException {
Customer c = new Customer();
c.setName("Gabbar Singh");
c.setGender('M');
c.setDob(new Date(getDate(date).getTime()));
c.setAddress(address);
return c;
}
private Address getAddress(String street, String city, String state, String zipcode) {
Address address = new Address();
address.setStreet("MG Road");
address.setCity("Mysore");
address.setState("KA");
address.setZipCode("511001");
return address;
}
private java.util.Date getDate(String dateStr) throws ParseException {
SimpleDateFormat sd = new SimpleDateFormat("YYYY-MM-DD");
return sd.parse(dateStr);
}
/**
* The method throws LazyInitializationException when lazy = "true" is set in the Customer.hbm.xml mapping file because we are trying to load
* address object after the current unit of work or session has been closed. To fix above, either set lazy = "false" in the mapping file or load
* the address object before the session is closed
*/
@Test(expected = LazyInitializationException.class)
public void testLoadCustomerAddressAfterSessionClosed() {
Session session = null;
Transaction txn = null;
Customer c = null;
Address address = null;
String zipCode = null;
try {
session = lazySessionFactory.openSession();
txn = session.beginTransaction();
c = (Customer) session.get(Customer.class, 1);
// Gets the proxy object if lazy="true" is set
address = c.getAddress();
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
zipCode = address.getZipCode(); // throws LazyInitializationException as session has been closed
System.out.println("Name: " + c.getName() + " Address: " + zipCode);
}
@Test
public void testLoadCustomerAddressLazyFetch() {
Session session = null;
Transaction txn = null;
Customer c = null;
Address address = null;
String zipCode = null;
try {
session = lazySessionFactory.openSession();
txn = session.beginTransaction();
c = (Customer) session.get(Customer.class, 1); // Query is fired to retrieve customer object
address = c.getAddress();
zipCode = address.getZipCode(); // Query is fired to retrieve address object
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
System.out.println("Name: " + c.getName() + " Address: " + zipCode);
}
@Test
public void testLoadCustomerAddressEagerFetch() {
Session session = null;
Transaction txn = null;
Customer c = null;
Address address = null;
String zipCode = null;
try {
session = eagerSessionFactory.openSession();
txn = session.beginTransaction();
c = (Customer) session.get(Customer.class, 1); // Queries are fired to retrieve customer and address object
address = c.getAddress();
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
zipCode = address.getZipCode(); // Address has already been loaded
System.out.println("Name: " + c.getName() + " Address: " + zipCode);
}
/**
* When lazy = "true", the following test case throws Initialization exception The c.getAddress() returns a proxy to Address object. As the
* session has been closed already, the proxy object is not able to fetch the actual address object The code works when we set lazy = "true"
*/
@Test(expected = LazyInitializationException.class)
public void testListCustomers() {
List<Customer> customerList = null;
Session session = null;
Transaction txn = null;
try {
session = lazySessionFactory.openSession();
txn = session.beginTransaction();
Query query = session.createQuery("from Customer");
customerList = query.list();
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
for (Customer c : customerList) {
System.out.println("Name: " + c.getName() + " Address: " + c.getAddress().getCity());
}
}
@Test
public void testListCustomersEagerFetch() {
List<Customer> customerList = null;
Session session = null;
Transaction txn = null;
try {
session = eagerSessionFactory.openSession();
txn = session.beginTransaction();
Query query = session.createQuery("from Customer");
customerList = query.list();
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
for (Customer c : customerList) {
System.out.println("Name: " + c.getName() + " Address: " + c.getAddress().getCity());
}
}
@Test
public void testListAddresses() {
List<Address> addressList = null;
Session session = null;
Transaction txn = null;
try {
session = lazySessionFactory.openSession();
txn = session.beginTransaction();
Query query = session.createQuery("from Address");
addressList = query.list();
txn.commit();
} catch (HibernateException he) {
txn.rollback();
throw he;
} finally {
session.close();
}
for (Address a : addressList) {
System.out.println("Street: " + a.getStreet() + " State: " + a.getState() + " Zip: " + a.getZipCode());
}
}
}