Both of these methods and saveOrUpdate() method are intended for reattaching a detached object. The session.lock() method simply reattaches the object to the session without checking or updating the database on the assumption that the database in sync with the detached object.
It is the best practice to use either session.update(..) or session.saveOrUpdate(). Use session.lock() only if you are absolutely sure that the detached object is in sync with your detached object or if it does not matter because you will be overwriting all the columns that would have changed later on within the same transaction.
Each interaction with the persistent store occurs in a new Session. However, the same persistent instances are reused for each interaction with the database. The application manipulates the state of detached instances originally loaded in another Session and then "reassociates" them using Session.update() or Session.saveOrUpdate().
// foo is an instance loaded by a previous Session
foo.setProperty("bar");
session = factory.openSession();
session.saveOrUpdate(foo);
session.flush();
session.connection().commit();
session.close();
You may also call lock() instead of update() and use LockMode.READ (performing a version check, bypassing all caches) if you are sure that the object has not been modified.
Cascade Save or Update - In one to Many- EXAMPLE
PROCESS_TYPE_LOV (PROCESS_TYPE_ID number, PROCESS_TYPE_NAME varchar) - TABLE
PROCESS (PROCESS_ID number,PROCESS_NAME varchar,PROCESS_TYPE_ID number)- TABLE
public class ProcessTypeBean {
private Long processTypeId;
private String processTypeName;
/**
* @return Returns the processTypeId.
*/
public Long getProcessTypeId() {
return processTypeId;
}
/**
* @param processTypeId The processTypeId to set.
*/
public void setProcessTypeId(Long processTypeId) {
this.processTypeId = processTypeId;
}
/**
* @return Returns the processTypeName.
*/
public String getProcessTypeName() {
return processTypeName;
}
/**
* @param processTypeName The processTypeName to set.
*/
public void setProcessTypeName(String processTypeName) {
this.processTypeName = processTypeName;
}
}
public class ProcessBean {
private Long processId;
private String processName = "";
private ProcessTypeBean processType;
public Long getProcessId() {
return processId;
}
/**
* @param processId The processId to set.
*/
public void setProcessId(Long processId) {
this.processId = processId;
}
/**
* @return Returns the processName.
*/
public String getProcessName() {
return processName;
}
/**
* @param processName The processName to set.
*/
public void setProcessName(String processName) {
this.processName = processName;
}
/**
* @return Returns the processType.
*/
public ProcessTypeBean getProcessType() {
return processType;
}
/**
* @param processType The processType to set.
*/
public void setProcessType(ProcessTypeBean processType) {
this.processType = processType;
}
}
It is possible to re-load an object and all its collections at any time, using the refresh() method. This is useful when database triggers are used to initialize some of the properties of the object.
For Example - Trigger on cat_name column. Trigger is updating hit_count column in the same Cat Table. When Insert data into Cat TABLE trigger update hit_count coulmn to 1. sess.refresh() reload all the data. No need again to select call.
sess.save(cat);
sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)
Cat fritz = (Cat) session.load(Cat.class, "1");
Return the Cat Object with key 1. If there is no Cat Object with key 1 then throw will throw an unrecoverable exception. If the class is mapped with a proxy, load() just returns an uninitialized proxy and does not actually hit the database until you invoke a method of the proxy. This behaviour is very useful if you wish to create an association to an object without actually loading it from the database. It also allows multiple instances to be loaded as a batch if batchsize is defined for the class mapping.
Cat fritz = (Cat) session.get(Cat.class, "1");
If you are not certain that a matching row exists, you should use the get() method, which hits the database immediately and returns null if there is no matching row.
Step 1. Put Hibernate properties in the classpath.
Step 2. Put .hbm.xml in class path.
Code is here to create session ...
package com.dao;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
/**
*
* @author JavaByKiran
*/
public class HibernateUtil {
protected static final Logger logger=Logger.getLogger(HibernateUtil.class);
public static String appHome = "No";
private static SessionFactory sessionFactory;
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTransaction = new ThreadLocal();
/**
* Initialize Hibernate Configuration
*/
public static void initMonitor(){
logger.info("Hibernate configure");
try {
logger.info("appHome"+appHome);
String path_properties = appHome+File.separatorChar+"hibernate.properties";
String path_mapping = appHome+File.separatorChar+"mapping_classes.mysql.hbm.xml";
//String ecache = appHome+File.separatorChar+"ehcache.xml";
Properties propHibernate = new Properties();
propHibernate.load(new FileInputStream(path_properties));
Configuration configuration = new Configuration();
configuration.addFile(path_mapping);
configuration.setProperties(propHibernate);
/* try {
CacheManager.create(ecache);
} catch (CacheException e) {
// logger.logError(e);
}*/
sessionFactory = configuration.buildSessionFactory();
} catch (Throwable ex) {
logger.error("Exception in initMonitor",ex);
throw new ExceptionInInitializerError(ex);
}
}
/**
* @return a Session Factory Object
*/
public static SessionFactory getSessionFactory() {
logger.info("Inside getSessionFactory method");
try {
if (sessionFactory == null) {
initMonitor();
}else {
//sessionFactory.getStatistics().logSummary();
}
} catch (Exception e) {
logger.error("Exception in getSessionFactory",e);
}
return sessionFactory;
}
/**
* @return Session . Start a Session
*/
public static Session getSession() {
Session s = (Session) threadSession.get();
logger.debug("session"+s);
if (s == null) {
s = getSessionFactory().openSession();
threadSession.set(s);
logger.debug("session 1 $"+s);
}
return s;
}
/**
* Close Session
*/
public static void closeSession(){
Session s = (Session) threadSession.get();
threadSession.set(null);
if (s != null && s.isOpen()) {
s.flush();
s.close();
}
}
/**
* Start a new database transaction.
*/
public static void beginTransaction(){
Transaction tx = null;
if (tx == null) {
tx = getSession().beginTransaction();
threadTransaction.set(tx);
}
}
/**
* Commit the database transaction.
*/
public static void commitTransaction(){
Transaction tx = (Transaction) threadTransaction.get();
try {
if ( tx != null ) {
tx.commit();
}
threadTransaction.set(null);
} catch (HibernateException ex) {
rollbackTransaction();
throw ex;
}
}
/**
* Rollback the database transaction.
*/
public static void rollbackTransaction(){
Transaction tx = (Transaction) threadTransaction.get();
try {
threadTransaction.set(null);
if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() ) {
tx.rollback();
}
} finally {
closeSession();
}
}
}
Session is a light weight and a non-threadsafe object (No, you cannot share it between threads) that represents a single unit-of-work with the database. Sessions are opened by a SessionFactory and then are closed when all work is complete.
Session is the primary interface for the persistence service. A session obtains a database connection lazily (i.e. only when required). To avoid creating too many sessions ThreadLocal class can be used as shown below to get the current session no matter how many times you make call to the currentSession() method.
public class HibernateUtil {
public static final ThreadLocal local = new ThreadLocal();
public static Session currentSession() throws HibernateException {
Session session = (Session) local.get();
//open a new session if this thread has no session
if(session == null) {
session = sessionFactory.openSession();
local.set(session);
}
return session;
}
}
session.save()
- Insert data into the table.
session.saveOrUpdate()
- Insert data if primary key not exist otherwise update .
Best way to handle is use of Criteria query.
Example : You have parent class.
public class Organization {
private long orgId;
private List messages;
}
Child class
public class Message {
private long messageId;
private Organization organization;
}
.hbm.xml file
<class name="com.bean.Organization" table="ORGANIZATION">
<bag name="messages" inverse="true" cascade="delete" lazy="false">
<key column="MSG_ID" />
<one-to-many class="com.bean.Message" />
</bag>
</class>
<class name="com.bean.Message" table="MESSAGE">
<many-to-one name="organization" column="ORG_ID" lazy="false"/>
</class>
Get all the messages from message table where organisation id = <any id>
Criteria query is :
session.createCriteria(Message.class).createAlias("organization","org").
add(Restrictions.eq("org.orgId",new Long(orgId))).add(Restrictions.in("statusCode",status)).list();
If you are using Hibernate then you don't need to learn specific SQL (like oracle,mysql), You have to user POJO class object as a table.
Don't need to learn query tuning. Hibernate criteria query automatically tuned the query for best performance.
You can use inbuild cache for storing data.
No need to create own connection pool, we can use c3po. It will give best results.
Don't need any join query which reduce performance and complex. Using hibernate you have to define in bean and hbm.xml file.
You can add filter in Hibernate which execute before you query fires and get the best performance.
EhCache is used for 2nd level cache to store all the redefined data like country table.