Hibernate
DOCS : https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html
POSTGRES: https://mvnrepository.com/artifact/org.postgresql/postgresql
HIBERNATE REPOS: https://mvnrepository.com/artifact/org.hibernate
If you encounter any compatabile issues. pick the right version of postgres..
<dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.1</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.2.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>5.2.2.Final</version> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.1</version> <type>pom</type> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.9</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.5</version> </dependency> </dependencies>
.What is Hibernate? Advantage over other persistent implementations?
As per as persistent implementation is concered hibernate is the best ORM tool because of the following feature
– Auto DDL( Data Defination Language ) support
– HQL Support (DB independent Queries)
– Cache Support
– PK(primary key) generator support
– Data Validation Support (using Annotations)
– All exceptions are runtime exceptions in Hibernate
– ORM(Object-relational Mapping) Support Collections, inheritance, polymorphism and (uni and bidirectional relationship). And also supports one-to-one, one-to-many and many-to-many associations.
– Batch updates
– Lazy Initialization
– OGM(Object-graph Mapping) (for DataBases like NO SQL)
– Search Feature
– in-Built connection-pool support.
– Support for native queries based on the dialect used.
– Support criteria queries (We can do join and compilated queries easily using criterial queries)
– No source code retranslation or byte code retranslation.
– Supports transaction management and concurrency control.
– No need to write jdbc statements.
High level APIs:
. Transient Object (normal java object )
. Persistent Object (once object is attched to Hibernate)
. Detached Object (once object removed from Hibernate)
. Session Factory
. Session
. Transaction
Low level API:(Used by hibernate API internally)
. TransactionFactory (normal java object )
. ConnectionProvider(Factory)
. JTA(Java Transaction API)
. JNDI API
. JDBC API
SessionFactory :(org.hibernate.SessionFactory)
– SessionFactory is a thread-safe
– Once SessionFactory for one DB for the entire Application
– It's factory for session.
– It acts as a client for ConnectionProvider
Session :(org.hibernate.Session)
– Session is single threaded short lived object represents a conversation between application and database.
– Its a factory for Transactions
Transaction: (org.hibernate.Transaction)
– Transaction is a single threaded shortlived object used by the application to specify the atomic untis of work.
– Abstracts or hides the application from JDBC, JTA Transactions
– A session might span serval transactions in some cases.
ConnectionProvider (org.hibernate.connection.ConnectionProvider)
-Its a factory of JDBC connections.
-Hides the application from underlying datasource and driver manager.
-Its not exposed to applications, i.e used by hibernate framework internally
TransactionFactory (org.hibernate.TransactionFactory)
– It's a factory for transaction object and its not exposed to Application
Persistent Object :
– These are shortlived single threaded objects containing persistent state. These might be oridnary java beans or pojo(plain old java objects)
– The only special thing about these objects is that – they assoicates with exactly one session.
– As soon as the session is closed they will be detached and free to use any where
Transient and Detached Obejects:
– These objects are not associated with the session
– The transient instance has never been assoicated with any persistent context i.e it has not persistent identity
In order to develop Hibernate Application
1. pojo class
2. mapping file
3. configuration file
Rules:
..Pojo class must contain required persistent fields
..Pojo class must contain default constructor
..In Pojo, each property should contain public setter/getter
..Mapping file
${tablename/objectname}.hbm.xml
student.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.bellinfo.hibernate.Student" table="STUDENT" schema="hibernate1"> <id name="studentId"/> <property name="name"/> <property name="createdDate"/> </class> </hibernate-mapping>
..Configuration file
hibernate.cfg.xml
-DB Driver proerpties
-DB ConnectionPool properties
-hibernate Commands
-Attach mapping file
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">org.postgresql.Driver</property> <property name="hibernate.connection.url">jdbc:postgresql://localhost/hibernate1</property> <property name="hibernate.connection.username">postgres</property> <property name="hibernate.connection.password">bellinfo</property> <property name="hibernate.dialect">org.hibernate.dialect.ProgressDialect</property> <!-- create, update, create-drop, validate --> <property name="hbm2ddl.auto">create</property> <property name="hibernate.default_schema">hibernate1</property> <property name="show_sql">true</property> <mapping resource="student.hbm.xml"/> </session-factory> </hibernate-configuration>
Equivalent Java Code for CFG file
public static SessionFactory newSessionFactory() { Properties properties = new Properties(); properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect"); properties.put("hibernate.hbm2ddl.auto", "update"); properties.put("hibernate.show_sql", "true"); properties.put("hibernate.connection.driver_class", "org.postgresql.Driver"); properties.put("hibernate.connection.url", "jdbc:postgresql://127.0.0.1:5432/mydb"); properties.put("hibernate.connection.username", "admin"); properties.put("hibernate.connection.password", "IscanU#1"); return new Configuration() .addProperties(properties) .addAnnotatedClass(Customer.class) .addAnnotatedClass(Department.class) .addAnnotatedClass(Employee.class) .buildSessionFactory( new StandardServiceRegistryBuilder() .applySettings(properties) .build() ); }
Java Code to connect
public static void main(String args[]){ Student std = new Student(); std.setStudentId(1); std.setName("siva"); std.setCreatedDate(new Date()); //student state is transient Configuration cfg = new Configuration().configure("hibernate.cfg.xml"); SessionFactory sf = cfg.buildSessionFactory(); Session session = sf.openSession(); Transaction transaction = session.beginTransaction(); session.save(std); //object state is persistent transaction.commit(); //object will be moved to database session.evict(std); //from here object is eligible for garbage collection. session.close(); sf.close(); }
hbm2ddl.auto allows the following options:
create – drop exsisting tables and create new tables
update – If any table required, it just creates. If required, it will do alter operation. else it will as is
create-drop – drop-create-drop when you call sessionfactory.close() then it will drop the tables.
validate – validates mapping schema against table schema. Required column not found in table.
..insert record:
save(object) -> rt primary key(Integer)
persist(object) -> rt void
session.saveOrUpdate(object) -> rt void -> if data avaliable in RDB and if your object modified for any attribute then it will just update column (which means select and update or insert)
..update record: (possible on non-pk feilds, update will update entire column)
session.update(object) ->If your session contains already the update record then update() doesn't work
session.merge(object) – it will update the data at any cost
..delete record:
-session.delete(object)
..select record: (Transaction is not required)
Object get(Class var1, Serializable var2)
– select will be called whenever you trigger the get() method
– earger loading and it gurantee the record
– if record not found, then it will return null and end-up getting null pointer exception.
Object load(Class var1, Serializable var2)
– select will be called whenever you try to access non-pk attribute
– so, you don't any null pointer exception.
– lazy loading and it doesn't gurantee the record until you call whether the record is avaliable or not.
..Primary Key Auto Generators–
– assigned (default) * user is responsible
– increment * auto +1 increment
– sequence (DataBase and Application responsible)
– identity (DataBase should support)
– native ( sequence, identity, or hilo)
– foreign (
– hilo (increment by 32768)
– seqhilo
– custom generators
Postgres Dialects avalaible:
org.hibernate.dialect.PostgreSQL82Dialect
org.hibernate.dialect.ProgressDialect
CREATE SEQUENCE hibschema.hibernate_sequence1 INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 5 CACHE 1;
<id name="studentId" > <generator class="sequence"> <param name="sequence">registration_sequence</param> </generator> </id>
HQL: for crud operations
– Database independent
– Need to write queries based on your bean class and its attribute
DUL:
executeUpdate()
DRL :
uiqueResult()
list()
Insert :
String hql = "insert into StudentNew(studentId, name, createdDate) select s.studentId,s.name, s.createdDate from Student s"; Query q = session.createQuery(hql); int rows = q.executeUpdate(); System.out.println("no. of rows afftected :" + rows); transaction.commit(); session.close();
Update :
String hql_update = "update Student set name='teju' where studentId='1'"; Query q = session.createQuery(hql_update); int rows = q.executeUpdate(); System.out.println("no. of rows afftected :" + rows); transaction.commit(); session.close();
Delete :
String hql_delete = "delete Student where studentId='1'"; Query q = session.createQuery(hql_delete); int rows = q.executeUpdate(); System.out.println("no. of rows afftected :" + rows); transaction.commit(); session.close();
Read :
Retrieve Student record where student id is 4
/* Retrieve Student record where student id is 4*/ String hql_select ="from Student where studentId='4'"; Query q = session.createQuery(hql_select); Student sd = (Student)q.uniqueResult(); System.out.println(sd); session.close();
Retrive all the student records
String hql_select ="from Student"; Query q = session.createQuery(hql_select); List<Student> sdList = q.list(); for(Student s:sdList){ System.out.println(s); } transaction.commit(); session.close();
Retrive student names from Student
String hql_select ="select name from Student "; Query q = session.createQuery(hql_select); List<String> nameList = q.list(); for(String s:nameList){ System.out.println(s); } session.close();
To Extract more then one column
String hql_select ="select studentId, name from Student "; Query q = session.createQuery(hql_select); List<Object> list = q.list(); for(Object obj:list){ Object[] array = (Object[]) obj; System.out.println(array[0]); System.out.println(array[1]); } session.close();
Aggregate Functions avg, count, first, last, max, min, sum
String hql_select ="select avg(studentId) from Student"; Query q = session.createQuery(hql_select); Double maxID = (Double)q.uniqueResult(); System.out.println(maxID.doubleValue()); session.close();
Criteria Queries :
-used for select operation by applying conditions
-Restrcitions are for conditions (eq, gt, )
-Projections are for particular column operations and aggregate functions
Simple Criteria to retrive all records from Student table
Criteria c = session.createCriteria(Student.class); List<Student> studList = c.list(); for(Student s:studList){ System.out.println(s); } session.close();
extract a student data where studentId equals 4
Criteria c = session.createCriteria(Student.class); Criterion cr = Restrictions.eq("studentId", 4); c.add(cr); Student s =(Student) c.uniqueResult(); System.out.println(s); session.close();
extract all the student objects where studentid greater than 4
Criteria c = session.createCriteria(Student.class); Criterion cr = Restrictions.gt("studentId", 4); c.add(cr); List<Student> list = c.list(); for(Student s:list) System.out.println(s); session.close();
extract all the student names where studentid greater than 4
Criteria c = session.createCriteria(Student.class); Projection p = Projections.property("name"); Criterion cr = Restrictions.gt("studentId", 4); c.setProjection(p); c.add(cr); List<String> list = c.list(); for(String s:list) System.out.println(s); session.close();
extract all the student names and studentId where studentid greater than 4
/* extract all the student names and studentId where studentid greater than 4*/ Criteria c = session.createCriteria(Student.class); Projection pName = Projections.property("name"); Projection pId = Projections.property("studentId"); Criterion cr = Restrictions.gt("studentId", 4); ProjectionList pl = Projections.projectionList(); pl.add(pName); pl.add(pId); c.setProjection(pl); c.add(cr); List<Object> list = c.list(); for(Object o:list){ Object[] arr = (Object[]) o; System.out.println(arr[0]); System.out.println(arr[1]); } session.close();
Aggregate functions: get average of studentID
/* Aggregate functions: get average of studentID */
Criteria c = session.createCriteria(Student.class);
Projection pAvg = Projections.avg("studentId");
c.setProjection(pAvg);
double d = ((Double)c.uniqueResult()).doubleValue();
System.out.println(d);
session.close();
ORM Relations:
1. Inheritance ( Is-a releation)
– table-per-class
<hibernate-mapping> <class name="com.bellinfo.hib.inheritance.Payment" table="PAYMENT" schema="hibschema" > <id name="paymentId"> <generator class="increment"/> </id> <discriminator column="PAYMENT_TYPE" type="string"/> <property name="amount" column="AMOUNT"/> <subclass name="com.bellinfo.hib.inheritance.CreditCardPayment" discriminator-value="CREDIT"> <property name="cardNumber" column="CARD_NUMBER"/> <property name="cvv" column="CVV"/> </subclass> <subclass name="com.bellinfo.hib.inheritance.ChequePayment" discriminator-value="CHEQUE"> <property name="chequeNo" column="CHEQUE_NUMBER"/> <property name="chequeBy" column="CHEQUE_BY"/> </subclass> </class> </hibernate-mapping>
– table-per-subclass
<hibernate-mapping> <class name="com.bellinfo.hib.inheritance.Payment" table="PAYMENT" schema="hibschema" > <id name="paymentId" column="PAYMENT_ID"> <generator class="increment"/> </id> <property name="amount" column="AMOUNT"/> <joined-subclass name="com.bellinfo.hib.inheritance.CreditCardPayment" table="CREDIT_PAYMENT"> <key column="PAYMENT_ID"/> <property name="cardNumber" column="CARD_NUMBER"/> <property name="cvv" column="CVV"/> </joined-subclass> <joined-subclass name="com.bellinfo.hib.inheritance.ChequePayment" table="CHEQUE_PAYMENT"> <key column="PAYMENT_ID"/> <property name="chequeNo" column="CHEQUE_NUMBER"/> <property name="chequeBy" column="CHEQUE_BY"/> </joined-subclass> </class> </hibernate-mapping>
– table-per-concrete class
<hibernate-mapping> <class name="com.bellinfo.hib.inheritance.Payment" table="PAYMENT" schema="hibschema" > <cache usage="read-write"/> <id name="paymentId" column="PAYMENT_ID"> <generator class="increment"/> </id> <property name="amount" column="AMOUNT"/> <union-subclass name="com.bellinfo.hib.inheritance.CreditCardPayment" table="CREDIT_PAYMENT"> <property name="cardNumber" column="CARD_NUMBER"/> <property name="cvv" column="CVV"/> </union-subclass> <union-subclass name="com.bellinfo.hib.inheritance.ChequePayment" table="CHEQUE_PAYMENT"> <property name="chequeNo" column="CHEQUE_NUMBER"/> <property name="chequeBy" column="CHEQUE_BY"/> </union-subclass> </class> </hibernate-mapping>
Reference : https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/inheritance.html
2. Assocaition ( Has-a )
– one-to-many
<hibernate-mapping> <class name="com.bellinfo.hib.associations.onetomany.Product" table="PRODUCT" schema="hibschema" > <id name="productId" column="PRODUCT_ID" > <generator class="increment"> </generator> </id> <property name="productName" column="PRODUCT_NAME"/> <set name="parts" cascade="all"> <key column="PRODUCT_ID" not-null="true"></key> <one-to-many class="com.bellinfo.hib.associations.onetomany.Part"/> </set> </class> </hibernate-mapping>
– one-to-many
– many-to-many
– one-to-one
Pagination : using HQL and Criteria
HQL
String hql_retirve ="from CreditCardPayment"; Query q =session.createQuery(hql_retirve); int initial = 1; int max =3; int count =1; HashMap<Integer, List<CreditCardPayment>> hmPagination = new HashMap<>(); System.out.println(q.list().size()); for(int i=0;i<q.list().size();i++){ q.setFirstResult(initial); q.setMaxResults(max); List<CreditCardPayment> listcc = q.list(); hmPagination.put(count, listcc); count++; initial = max+1; max = max +3; } for(Map.Entry<Integer, List<CreditCardPayment>> entry:hmPagination.entrySet()){ System.out.println(entry.getKey()); for(CreditCardPayment ccp:entry.getValue()){ System.out.println(ccp); } }
Criteria :
criteria.setFirstResult(1);
criteria.setMaxResults(5);
Cache Support:
– Reduce database calls
– Improve application performance
1. Session level – per user and its a default cache
Session ses1 = sf.openSession(); Student c1 = (Student)ses1.load(Student.class, 5); //This one is coming from session c1 = (Student)ses1.load(Student.class, 5);
2. SessionFactory level – per entire application
a.Enable second-level cache
b.Configure cache factory class
c.Define ehcache
d.configure ehcache
e.configure cache usage in hbm file
POM FILE
<dependencies> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.3-1100-jdbc41</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.2.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>4.3.2.Final</version> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.1</version> <type>pom</type> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.9</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.5</version> </dependency> </dependencies>
CFG FILE
<!-- enable second-level cache --> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.use_query_cache">true</property> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <property name="net.sf.ehcache.configurationResourceName">ehcache.xml</property>
EHCACHE.XML
<?xml version='1.0' encoding='UTF-8'?> <ehcache xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:noNamespaceSchemaLocation='http://ehcache.org/ehcache.xsd' updateCheck="true" monitoring="autodetect" dynamicConfig="true"> <diskStore path="java.io.tmpdir/ehcache" /> <defaultCache maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30" maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" statistics="true"> <persistence strategy="localTempSwap" /> </defaultCache> <cache name="com.bellinfo.hib.inheritance.CreditCardPayment" maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="60" timeToLiveSeconds="60"> <persistence strategy="localTempSwap" /> </cache> <cache name="org.hibernate.cache.internal.StandardQueryCache" maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120"> <persistence strategy="localTempSwap" /> </cache> <cache name="org.hibernate.cache.spi.UpdateTimestampsCache" maxEntriesLocalHeap="5000" eternal="true"> <persistence strategy="localTempSwap" /> </cache> </ehcache>
HBM FILE
<hibernate-mapping> <class name="com.bellinfo.hibernate.Student" table="STUDENT" schema="hibschema" > <cache usage="read-only"/> <id name="studentId" > <generator class="native"> </generator> </id> <property name="name"/> <property name="createdDate"/> </class> </hibernate-mapping>
3. Query Cache –
References : https://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/collections.html
Annnotation Based Configuration:
TABLE-PER-SUBCLASS (JOINED)
@Entity @Table(name = "Payment") @Inheritance(strategy=InheritanceType.JOINED) public class Payment { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "id") protected int id; @Column(name="amount") protected String amount; public Payment(String amount) { this.amount = amount; } }
@Entity @Table(name="credit_card") public class CreditCardPayment extends Payment{ @Column private String ccNumber; @Column private String cccvv; public CreditCardPayment(String amount, String ccNumber, String cccvv) { super(amount); this.ccNumber = ccNumber; this.cccvv = cccvv; } }
@Entity @Table(name="check_pay") public class ChequePayment extends Payment { @Column(name="chequeNo") private String chequeNo; @Column(name="chequeBy") private String chequeBy; public ChequePayment(String amount, String chequeNo, String chequeBy) { super(amount); this.chequeNo = chequeNo; this.chequeBy = chequeBy; } }
ONE TABLE
@Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="personType", discriminatorType=DiscriminatorType.STRING ) @DiscriminatorValue("Person") @Table(name="person") public class Person implements Serializable { }
@Entity @Table(name="student") @DiscriminatorValue("Student") public class Student extends Person implements Serializable { private static final long serialVersionUID = 1L; @Column(name="class_name") private String className; }
TABLE-PER-CLASS
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Table(name="person") public class Person implements Serializable { private static final long serialVersionUID = 1L; }
@Entity public class Student extends Person implements Serializable { private static final long serialVersionUID = 1L; @Column(name="class_name") private String className; }
ASSOCIATIONS
ONE-TO-MANY
package com.bellinfo.advanced.hibernate.entity; import javax.persistence.*; import java.util.Set; @Entity public class Cart { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="cart_id") int id; @Column String name; @OneToMany Set<Items> items; public Set<Items> getItems() { return items; } public void setItems(Set<Items> items) { this.items = items; } public Cart() { } public Cart(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; } @Override public String toString() { return "Cart{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
package com.bellinfo.advanced.hibernate.entity; import javax.persistence.*; @Entity public class Items { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) int id; @Column String itemId; @Column double cost; @ManyToOne @JoinColumn(name="cart_id", nullable = false) Cart cart1; public Items() { } public Items(String itemId, double cost, Cart cart1) { this.itemId = itemId; this.cost = cost; this.cart1 = cart1; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getItemId() { return itemId; } public void setItemId(String itemId) { this.itemId = itemId; } public double getCost() { return cost; } public void setCost(double cost) { this.cost = cost; } public Cart getCart1() { return cart1; } public void setCart1(Cart cart1) { this.cart1 = cart1; } @Override public String toString() { return "Items{" + "id=" + id + ", itemId='" + itemId + '\'' + ", cost=" + cost + ", cart1=" + cart1 + '}'; } } Demo:
package com.bellinfo.advanced.hibernate.inheritance; import com.bellinfo.advanced.hibernate.entity.Bike; import com.bellinfo.advanced.hibernate.entity.Cart; import com.bellinfo.advanced.hibernate.entity.Items; import com.bellinfo.advanced.hibernate.entity.Vehicle; import com.bellinfo.advanced.hibernate.util.HibernateUtil; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import java.util.HashSet; import java.util.Set; public class OneToMany { public static void main(String[] args) { SessionFactory sf = null; Session s = null; Transaction tx = null; try { sf = HibernateUtil.newSessionFactory(); s = sf.openSession(); tx = s.beginTransaction(); Cart cart = new Cart("fruits"); Items item1 = new Items("1",200,cart); Items item2 = new Items("2",400,cart); Set<Items> itemsSet = new HashSet<Items>(); itemsSet.add(item1); itemsSet.add(item2); cart.setItems(itemsSet); s.save(cart); s.save(item1); s.save(item2); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } finally { s.close(); sf.close(); } } }