Below are two tables with entity classes.
tbl_rules
| rule_id | rule_name |
@Entity
@Table(name = "db_user_name.tbl_rules")
public class Rule implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@GenericGenerator(name = "incre", strategy = "increment")
@GeneratedValue(generator = "incre")
@Column(name = "rule_id", unique = true, nullable = false)
private long ruleId;
@Column(name = "rule_name", length = 250)
private String ruleName;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "rules")
private Set<Benchmark> benchmarks = new HashSet<Benchmark>(0);
... getters and setters
}
tbl_benchmark
| benchmark_id | rule_id |
@Entity
@Table(name = "tbl_benchmark", catalog = "db_user_name")
@DynamicUpdate(value = true)
public class Benchmark implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "benchmark_id", unique = true, nullable = false)
private Long benchmarkId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rule_id", nullable = false)
private Rule rules;
.. getter and setters
}
Expose a deadlock problem with sql server dbin the following case
HibernateSessionManager.beginTransaction();- calling
saveRule(rule)// in the backend rule and comparing two tables are blocked (using the sql server locked tables query) - call
saveBenchmark(benchmark)// dead end with this method HibernateSessionManager.commit();
The code in which the deadlock occurs:
HibernateSessionManager.beginTransaction();
UserIdManager.setCurrentGroupId(2);
if (savingObjects.get(AmlConstants.USERCREDENTAILS_STRING) != null){
userCredentials = (UserCredentials) savingObjects.get(AmlConstants.USERCREDENTAILS_STRING);
Util.setAuditLogField(AmlConstants.USERIDSTRING);
this.getAmlDAOFactory().getUserCredentialsDAO().updateUserDetails(userCredentials);
if (savingObjects.get(AmlConstants.USERBRANCHMAPPING_STRING) != null){
userBranchMapping = (UserBranchMapping) savingObjects.get(AmlConstants.USERBRANCHMAPPING_STRING);
Util.setAuditLogField(AmlConstants.BRANCH_STRING);
this.getAmlDAOFactory().getUserBranchMappingDAO().saveUserBranchMapping(userBranchMapping);
}
}
HibernateSessionManager.commit();
saveRule:
@Override
public Rule saveRule(Rule rule) throws Exception {
try {
getSession().saveOrUpdate(rule);
getSession().flush();
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
}
return rule;
}
saveBenchmark:
@Override
public Benchmark saveBenchMark(Benchmark benchmark) throws Exception {
try {
if (benchmark.getBenchmarkId() == null)
benchmark.setBenchmarkId(getBenchmarkCount() + 1);
getSession().clear();
getSession().saveOrUpdate(benchmark);
getSession().flush();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
logger.error("Exception while saving benchmark " + e.getMessage(), e);
}
return benchmark;
}
Spring -Hib confg file:
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
..
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">com.aml.hibernate.SQLServerCustomeDialect</prop>
<prop key="hibernate.character_encoding">UTF-8</prop>
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.generate_statistics">false</prop>
</props>
</property>
..
HibernateSessionManager.java
public class HibernateSessionManager {
public static Logger logger = Logger.getLogger(HibernateSessionManager.class);
public static final ThreadLocal<Session> currentSession = new ThreadLocal<Session>();
public static final ThreadLocal<java.util.List<Session>> sessionList = new ThreadLocal<java.util.List<Session>>();
public static final ThreadLocal<Transaction> transaction = new ThreadLocal<Transaction>();
public static final ThreadLocal<Map<String, Transaction>> transactionMap = new ThreadLocal<Map<String, Transaction>>();
public static final ThreadLocal<String> callerXPath = new ThreadLocal<String>();
public static Session currentSession(SessionFactory sessionFactory) throws HibernateException {
Session s = (Session) currentSession.get();
if (s == null || !s.isOpen())
{
s = sessionFactory.openSession();
currentSession.set(s);
if(sessionList.get()==null)
sessionList.set(new LinkedList<Session>());
sessionList.get().add(s);
logger.debug("Opened new session:"+currentSession.get().hashCode());
}else{
logger.debug("returning existing session:"+currentSession.get().hashCode());
}
return s;
}
public static void closeSession() throws HibernateException {
currentSession.set(null);
transaction.set(null);
callerXPath.set(null);
try{
if(sessionList.get()!=null)
for (int i = 0; i < sessionList.get().size(); i++) {
Session s = sessionList.get().get(i);
try{
if (s != null && s.isOpen())
s.close();
logger.debug("Closed session - session local:"+ (s!=null?s.hashCode(): ""));
}catch (Exception e) { logger.debug("Error while closing session: ", e); }
}
transactionMap.get().clear();
}catch (Exception e) { logger.debug("Error while closing session: ", e); }
sessionList.set(null);
transactionMap.set(null);
}
public static boolean beginTransaction(){
try{
logger.debug("beginTransaction............... ");
Transaction t = transaction.get();
if(t == null && callerXPath.get()==null){
Session s = currentSession.get();
t = s.beginTransaction();
t.registerSynchronization(new Synchronization() {
@Override
public void beforeCompletion() {
logger.debug("Transaction-beforeCompletion............... ");
}
@Override
public void afterCompletion(int status) {
logger.debug("Transaction-afterCompletion............... "+status);
}
});
transaction.set(t);
callerXPath.set(getCallerMethodInvolvedinTransaction());
if(transactionMap.get()==null)
transactionMap.set(new HashMap<String, Transaction>());
transactionMap.get().put(callerXPath.get(), t);
logger.debug("Started new hibernate transaction:"+t);
}
}catch (Exception e) {
logger.error("Error while starting new transaction: ", e);
return false;
}
return true;
}
public static void rollback(){
try{
Transaction t = transactionMap.get().get(callerXPath.get());
if(t != null){
t.rollback();
logger.debug("Roll back success on transaction:"+t);
}
}catch (Exception e) {
logger.error("Exception while trying to rollback", e);
}
}
public static void commit(){
try{
logger.debug("commit............... ");
Transaction t = transaction.get();
if(t != null
&& callerXPath.get()!=null && callerXPath.get().equals(getCallerMethodInvolvedinTransaction())){
t.commit();
currentSession.get().clear();
currentSession.set(null);
transaction.set(null);
callerXPath.set(null);
logger.debug("Commit success on transaction:"+t);
}
}catch (Exception e) {
logger.error("Exception while trying to commit", e);
}
}
public static String getCallerMethodInvolvedinTransaction() {
try{
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
return stElements[3].toString().split("\\(")[0];
}catch (Exception e) {
logger.error("" , e);
}
return null;
}
}
But the same operating mode with oracle db(with hib oracle properties).