(點選上方公眾號,可快速關註)
來源:袁鳴凱 ,
blog.csdn.net/lifetragedy/article/details/7751059
2.6.8 ClassRoomDAOImpl類
package sky.org.dao.impl;
import java.sql.*;
import java.util.*;
import sky.org.dao.ClassRoomDAO;
import sky.org.util.db.ConnectionManager;
public class ClassRoomDAOImpl implements ClassRoomDAO {
public void addStudentClassRoom(String roomId, String sNo) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = ConnectionManager.getConnection();
pstmt = conn
.prepareStatement(ClassRoomDAOSql.ADD_STUDENT_CLASSROOM);
pstmt.setString(1, roomId);
pstmt.setString(2, sNo);
pstmt.executeUpdate();
} catch (Exception e) {
throw new Exception(“addStudentClassRoom:” + e.getMessage(), e);
} finally {
try {
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
} catch (Exception e) {
}
}
}
}
2.6.9 StudentDAO介面
package sky.org.dao;
import java.util.*;
import sky.org.bean.Student;
public interface StudentDAO {
public void addStudent(Student std) throws Exception;
}
2.6.10 StudentDAOImpl類
package sky.org.dao.impl;
import java.sql.*;
import javax.sql.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import sky.org.bean.Student;
import sky.org.dao.StudentDAO;
import sky.org.util.db.ConnectionManager;
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;
import java.text.*;
import sky.org.util.StringUtil;
public class StudentDAOImpl implements StudentDAO {
private Log logger = LogFactory.getLog(this.getClass());
public void addStudent(Student std) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = ConnectionManager.getConnection();
pstmt = conn.prepareStatement(StudentDAOSql.ADD_STUDENT);
pstmt.setString(1, std.getsNo());
pstmt.setString(2, std.getsName());
pstmt.setString(3, std.getsAge());
pstmt.setString(4, std.getGender());
pstmt.setDate(5, StringUtil.convertStrToDate(std.getSbirth()));
pstmt.executeUpdate();
} catch (Exception e) {
throw new Exception(“addStudent:” + e.getMessage(), e);
} finally {
try {
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
} catch (Exception e) {
}
}
}
public void delStudent(String sNo) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = ConnectionManager.getConnection();
pstmt = conn.prepareStatement(StudentDAOSql.DEL_STUDENT);
pstmt.setString(1, sNo);
pstmt.executeUpdate();
} catch (Exception e) {
throw new Exception(“delStudent:” + e.getMessage(), e);
} finally {
try {
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
} catch (Exception e) {
}
}
}
}
2.6.11 StudentDAOSql類
package sky.org.dao.impl;
public class StudentDAOSql {
public final static String ADD_STUDENT = “insert into t_student(sno, sname, sage, gender,
sbirth)values(?,?,?,?,?)”;
}
2.6.12 ClassRoomDAOSql類
package sky.org.dao.impl;
public class ClassRoomDAOSql {
public static String ADD_STUDENT_CLASSROOM = “insert into
t_student_classroom(room_id,sno)values(?,?)”;
}
2.6.13 ClassRoom 類
package sky.org.bean;
import java.io.*;
public class ClassRoom implements Serializable {
private String roomId = “”;
private String roomName = “”;
public String getRoomId() {
return roomId;
}
public void setRoomId(String roomId) {
this.roomId = roomId;
}
public String getRoomName() {
return roomName;
}
public void setRoomName(String roomName) {
this.roomName = roomName;
}
}
2.6.14 Student類
package sky.org.bean;
import java.io.*;
public class Student implements Serializable {
public String getsNo() {
return sNo;
}
public void setsNo(String sNo) {
this.sNo = sNo;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
public String getsAge() {
return sAge;
}
public void setsAge(String sAge) {
this.sAge = sAge;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
private String sNo = “”;
private String sName = “”;
private String sAge = “”;
private String gender = “”;
private String sbirth = “”;
private String classRoomId = “”;
private String classRoomName = “”;
public String getClassRoomId() {
return classRoomId;
}
public void setClassRoomId(String classRoomId) {
this.classRoomId = classRoomId;
}
public String getClassRoomName() {
return classRoomName;
}
public void setClassRoomName(String classRoomName) {
this.classRoomName = classRoomName;
}
public String getSbirth() {
return sbirth;
}
public void setSbirth(String sbirth) {
this.sbirth = sbirth;
}
}
2.6.15 StudentCRUD類(執行主類)
package sky.org.test;
import sky.org.bean.Student;
import sky.org.service.StudentService;
import sky.org.service.impl.StudentServiceImpl;
public class StudentCRUD {
public void addStudent() throws Exception {
StudentService stdService = new StudentServiceImpl();
Student std = new Student();
std.setsNo(“101”);
std.setsName(“abc”);
std.setSbirth(“1977/01/01”);
std.setsAge(“35”);
std.setGender(“m”);
std.setClassRoomId(“1”);
std.setClassRoomName(“class1”);
stdService.addStudent(std);
}
public static void main(String[] args) {
StudentCRUD testStudentCRUD = new StudentCRUD();
try {
testStudentCRUD.addStudent();
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}
三、Hibernate裡的ThreadLocal
Hibernate在事務操作中也支援ThreadLocal的作法,我們這邊指的是不用Spring去做代理,而直接用Hibernate。即:
Service Method{
hbDAO1.doSomething();
hbDAO2.doSomething();
hbDAO3.doSomething();
。。。
}
Hibernate版本3後增加了新特性,即getCurrentSession()。
3.1 getCurrentSession與openSession的區別
3.1.1 openSession
我們傳統的做法是openSession即:
public void testUser() throws Exception {
Transaction tran = null;
SessionFactory factory = null;
UserDAO userDAO = new UserDAOImpl();
try {
factory = HibernateUtil.getInstance().getSessionFactory();
Session session = factory.openSession();
tran = session.beginTransaction();
TUser testUser = new TUser();
testUser.setId(new Integer(i));
testUser.setName(“abc”);
userDAO.addUser(testUser);
tran.commit();
} catch (Exception e) {
tran.rollback();
throw new Exception(e);
} finally {
try{
if(session!=null){
session.close();
session=null();
}
}catch(Excepton e){}
}
}
這樣做,能夠保證我們每次在finally塊中正確關閉session,但是,如果我們也遇上了這樣的case即:
Service Method{
hbDAO1.doSomething();
hbDAO2.doSomething();
hbDAO3.doSomething();
。。。
}
這時,我們如果用的是openSession,應該怎麼辦?
解決方案一:
自己用ThreadLocal樣式寫一個SessionManagement類,來維護這個session。
解決方案二:
把在Service方法中開啟的session,傳到每個dao方法中,使每個dao方法使用同一個session,最後在Service方法中去關閉它(很爛的做法)。
下麵我們來看看Hibernate自身提供的getCurrentSession()的做法吧
3.1.2 getCurrentSession
要使用這個getCurrentSession,你的hibernate的設定必須如下(紅色加粗部分顯示-就喜歡粗J):
/span>
“-//Hibernate/Hibernate Configuration DTD 3.0//EN”
“http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd”>
jdbc:oracle:thin:@localhost:1521:myorcl
org.hibernate.dialect.Oracle9Dialect
oracle.jdbc.OracleDriver
然後上述程式碼將變成如下的樣子:
public void testUser() throws Exception {
Transaction tran = null;
SessionFactory factory = null;
UserDAO userDAO = new UserDAOImpl();
try {
factory = HibernateUtil.getInstance().getSessionFactory();
Session session = factory.getCurrentSession();
tran = session.beginTransaction();
for (int i = 0; i < 100; i++) {
TUser testUser = new TUser();
testUser.setId(new Integer(i));
testUser.setName(“abc”);
userDAO.addUser(testUser);
}
tran.commit();
} catch (Exception e) {
tran.rollback();
throw new Exception(e);
} finally {
ThreadLocalSessionContext.unbind(factory);
}
}
而你的每個DAO方法中的程式碼是這樣實現的:
public void addUser(TUser user) throws Exception {
SessionFactory factory = HibernateUtil.getInstance()
.getSessionFactory();
Session session = factory.getCurrentSession();
session.save(user);
}
是不是很方便的哈。
3.1.3 openSession與getCurrentSession的區別
嚴重註意下麵幾點:
-
openSession一旦被呼叫,必須且一定要在finally塊中close,要不然你就等著out of memory吧;
-
如果你使用的是getCurrentSession,那麼你不能在finally塊中呼叫”session.close()”,不行你可以在finally塊中用try-catch把session.close();包起來,然後在catch{}塊中丟擲這個exception,這個exception將會是:sessionhas been already closed。
因為:
l 如果你用的是getCurrentSession,那麼它在session.commit()或者是session.rollback()時就已經呼叫了一次session.close()了,因此你只要正確放置session.commit()與rollback()即可。
l 你必須在finally塊中呼叫”ThreadLocalSessionContext.unbind(factory);”,以使得當前的事務結束時把session(即dbconnection)還回db connection pool中
如果你使用的是getCurrentSession,那麼就算你是一個簡單的select陳述句,也必須包含在:
tran = session.beginTransaction();
//your select hibernate query
tran.commit();
這樣的事務塊中,要不然它將會丟擲這樣的一個錯誤:
NoHibernate Session bound to thread, and configuration does not allow creation ofnon-transactional
看下麵的例子:
try {
factory = HibernateUtil.getInstance().getSessionFactory();
Session session = factory.getCurrentSession();
tran = session.beginTransaction();
TUser testUser = userDAO.getUserByID(“1”);
log.info(“user id====”+testUser.getId()+” user name====”+testUser.getName());
tran.commit();
} catch (Exception e) {
tran.rollback();
throw new Exception(e);
} finally {
ThreadLocalSessionContext.unbind(factory);
}
可以看到我們的查詢是被tran=session.beginTransaction一直到tran.commit()或者是tran.rollback()結束的,如果,你把你的hibernate查詢移到了tran=session.beginTransaction的上面。。。就會拋上述這個錯誤。
3.1.4 getCurrentSession帶來的問題
getCurrentSession非常好,不需要我們自己寫ThreadLocal只需要在hibernate.cfg的配置檔案中聲音一下就可以獲得ThreadLocal的好處,便於我們劃分我們的程式的層次與封裝,帶也帶來了一定的效能問題。
特別是“如果你使用的是getCurrentSession,那麼就算你是一個簡單的select陳述句,也必須包含在事務塊中”。這給我們帶來了很大的問題。
因此,本人建議,在碰到如果:
-
一個service方法中只有單個dao操作且此操作是一個select類的操作,請使用openSession,並且即時在finally塊中關閉它;
-
如果一個service方法中涉及到多個dao操作,請一定使用getCurrentSession;
-
如果一個service方法中混合著select操作,delete, update, insert操作。請按照下述原則:
-
將屬於select的操作,單獨做成一個dao方法,該dao使用openSession並且在finally塊中及時關閉session,該dao只需要傳回一個java的object如:List
即可,如果出錯將exception拋回給呼叫它的service方法。 -
對於其它的delete, insert, update的dao操作,請使用getCurrentSession。
-
忌諱,把select類的操作放在“事務”中。
系列
看完本文有收穫?請轉發分享給更多人
關註「ImportNew」,提升Java技能