轉自:http://www.blogjava.net/DoubleJ/archive/2008/03/04/183781.html
Hibernate 3.x 提供的session的檢索策略默認爲延時加載.他有以下優點:
減少數據庫併發性
減少數據的IO次數
下面的例子是關於session的延時加載的例子.
建立數據庫example1
2# ---------------------------------------
3# Host : localhost
4# Port : 3306
5# Database : example1
6
7
8/**//*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
9/**//*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
10/**//*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
11/**//*!40101 SET NAMES gb2312 */;
12
13SET FOREIGN_KEY_CHECKS=0;
14
15DROP DATABASE IF EXISTS `example1`;
16
17CREATE DATABASE `example1`
18 CHARACTER SET 'gbk'
19 COLLATE 'gbk_chinese_ci';
20
21USE `example1`;
22
23#
24# Structure for the `department` table :
25#
26
27DROP TABLE IF EXISTS `department`;
28
29CREATE TABLE `department` (
30 `d_id` int(11) NOT NULL auto_increment,
31 `d_name` varchar(20) NOT NULL,
32 PRIMARY KEY (`d_id`),
33 UNIQUE KEY `d_name` (`d_name`)
34) ENGINE=InnoDB DEFAULT CHARSET=gb2312;
35
36#
37# Data for the `department` table (LIMIT 0,500)
38#
39
40INSERT INTO `department` (`d_id`, `d_name`) VALUES
41 (1,'Office');
42
43COMMIT;
44
45#
46# Structure for the `emplyee` table :
47#
48
49DROP TABLE IF EXISTS `emplyee`;
50
51CREATE TABLE `emplyee` (
52 `e_id` int(11) NOT NULL auto_increment,
53 `e_name` varchar(20) NOT NULL,
54 `e_login_name` varchar(20) NOT NULL,
55 `e_password` varchar(20) NOT NULL,
56 `e_reg_date` date default NULL,
57 `d_id` int(11) default NULL,
58 PRIMARY KEY (`e_id`),
59 UNIQUE KEY `e_login_name` (`e_login_name`),
60 KEY `d_id` (`d_id`),
61 CONSTRAINT `emplyee_fk` FOREIGN KEY (`d_id`) REFERENCES `department` (`d_id`)
62) ENGINE=InnoDB DEFAULT CHARSET=gb2312;
63
64#
65# Data for the `emplyee` table (LIMIT 0,500)
66#
67
68INSERT INTO `emplyee` (`e_id`, `e_name`, `e_login_name`, `e_password`, `e_reg_date`, `d_id`) VALUES
69 (1,'YiJun','DoubleJ','windows','2008-03-01',1),
70 (2,'ZhangSan','Zs','windows','2008-03-04',1);
71
72COMMIT;
73
74
75
76/**//*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
77/**//*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
78/**//*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
新建一javaWeb工程,取名爲 DJ_HIBERNATE
在MyEclipse裏的database Explorer建立數據源,連接上example1數據庫,並將hibernate 3.0導入到工程中!
創建以下類:
org.dj.pojo.DepartmentPojo.java
import java.util.HashSet;
import java.util.Set;
public class DepartmentPojo {
private Integer did;
private String dname;
private Set<EmplyeePojo> emps = new HashSet<EmplyeePojo>(0);
public DepartmentPojo() {
// TODO Auto-generated constructor stub
}
public DepartmentPojo(String dname) {
super();
this.dname = dname;
}
public DepartmentPojo(Integer did, String dname) {
super();
this.did = did;
this.dname = dname;
}
public Integer getDid() {
return did;
}
public void setDid(Integer did) {
this.did = did;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public Set<EmplyeePojo> getEmps() {
return emps;
}
public void setEmps(Set<EmplyeePojo> emps) {
this.emps = emps;
}
}
並在org.dj.pojo包下創建DepartmentPojo.hbm.xml關係配置文件
2<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4<hibernate-mapping>
5 <class name="org.dj.pojo.DepartmentPojo" table="department">
6 <id name="did" column="d_id" type="java.lang.Integer">
7 <generator class="native"></generator>
8 </id>
9 <property name="dname" column="d_name"
10 type="java.lang.String">
11 </property>
12 <set name="emps">
13 <key column="d_id"></key>
14 <one-to-many class="org.dj.pojo.EmplyeePojo" />
15 </set>
16 </class>
17</hibernate-mapping>
再創建org.dj.pojo.EmplyeePojo類,
2
3import java.sql.Date;
4
5public class EmplyeePojo {
6 private Integer eid;
7
8 private String ename;
9
10 private String eloginName;
11
12 private String epassword;
13
14 private java.sql.Date eregDate;
15
16 private DepartmentPojo department;
17
18 public DepartmentPojo getDepartment() {
19 return department;
20 }
21
22 public void setDepartment(DepartmentPojo department) {
23 this.department = department;
24 }
25
26 public EmplyeePojo() {
27 // TODO Auto-generated constructor stub
28 }
29
30 public EmplyeePojo(String ename, String eloginName, String epassword,
31 Date eregDate) {
32 super();
33 this.ename = ename;
34 this.eloginName = eloginName;
35 this.epassword = epassword;
36 this.eregDate = eregDate;
37 }
38
39 public EmplyeePojo(Integer eid, String ename, String eloginName,
40 String epassword, Date eregDate) {
41 super();
42 this.eid = eid;
43 this.ename = ename;
44 this.eloginName = eloginName;
45 this.epassword = epassword;
46 this.eregDate = eregDate;
47 }
48
49 public Integer getEid() {
50 return eid;
51 }
52
53 public void setEid(Integer eid) {
54 this.eid = eid;
55 }
56
57 public String getEloginName() {
58 return eloginName;
59 }
60
61 public void setEloginName(String eloginName) {
62 this.eloginName = eloginName;
63 }
64
65 public String getEname() {
66 return ename;
67 }
68
69 public void setEname(String ename) {
70 this.ename = ename;
71 }
72
73 public String getEpassword() {
74 return epassword;
75 }
76
77 public void setEpassword(String epassword) {
78 this.epassword = epassword;
79 }
80
81 public java.sql.Date getEregDate() {
82 return eregDate;
83 }
84
85 public void setEregDate(java.sql.Date eregDate) {
86 this.eregDate = eregDate;
87 }
88
89}
90
再在org.dj.pojo包下創建與其對應的配置文件EmplyeePojo.hbm.xml
2<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4<hibernate-mapping>
5 <class name="org.dj.pojo.EmplyeePojo" table="emplyee">
6 <id name="eid" column="e_id" type="java.lang.Integer">
7 <generator class="native"></generator>
8 </id>
9 <property name="ename" column="e_name"
10 type="java.lang.String">
11 </property>
12 <property name="eloginName" column="e_login_name"
13 type="java.lang.String">
14 </property>
15 <property name="epassword" column="e_password"
16 type="java.lang.String">
17 </property>
18 <property name="eregDate" column="e_reg_date"
19 type="java.sql.Date">
20 </property>
21 <many-to-one name="department"
22 class="org.dj.pojo.DepartmentPojo" column="d_id">
23 </many-to-one>
24 </class>
25</hibernate-mapping>
再創建一個dao對象用來得到一個員工記錄,些類爲:
org.dj.dao.EmplyeeDao
2
3import java.io.Serializable;
4
5import org.dj.pojo.EmplyeePojo;
6import org.dj.util.HibernateSessionFactory;
7import org.hibernate.HibernateException;
8import org.hibernate.Session;
9import org.hibernate.Transaction;
10
11public class EmplyeeDao {
12 /** *//**
13 * 根據id得到用戶
14 *
15 * @param eid
16 * @return
17 */
18 public EmplyeePojo getEmplyee(Serializable eid) {
19 EmplyeePojo emp = null;
20 Session session = HibernateSessionFactory.getSession();
21 // Transaction trans = session.beginTransaction();
22 try {
23 emp = (EmplyeePojo) session.load(EmplyeePojo.class, eid);
24 // trans.commit();
25 } catch (HibernateException e) {
26 e.printStackTrace();
27 // trans.rollback();
28 } finally {
29 // HibernateSessionFactory.closeSession();
30 }
31 return emp;
32 }
33}
34
一開始.請去掉我的代碼註釋;
下面,我們去寫個Emplyee的Service類,寫一個業務處理的方法, 通得員工ID計算已註冊的天數
org.dj.service.EmplyeeManegerService
2
3import java.io.Serializable;
4import java.util.Calendar;
5
6import org.dj.dao.EmplyeeDao;
7import org.dj.pojo.EmplyeePojo;
8import org.dj.vo.EmplyeeVo;
9
10public class EmplyeeManegerService {
11 private EmplyeeDao empDao = new EmplyeeDao();
12 /** *//**
13 * 得到用戶註冊的天數(本網站的網齡)
14 * @param eid 用戶的id
15 * @return 網齬
16 */
17 public Long loadEmplyeeOnlineTime(Serializable eid){
18 EmplyeePojo emp = empDao.getEmplyee(eid);
19 java.sql.Date regDate = emp.getEregDate();
20 Long time = System.currentTimeMillis() - regDate.getTime();
21 long day = time/(24*60*60*1000);
22 return day;
23 }
24
25 public static void main(String[] args) {
26 Long day = new EmplyeeManegerService().loadEmplyeeOnlineTime(1);
27 System.out.println(day);
28 }
29}
30
裏面有個main寫的測試. 你去run的時候. 發現他會發生一個異常:
session was close;
解決這個方法,你可以這樣做.
先修改HibernateSessionFactory類.
2
3import org.hibernate.HibernateException;
4import org.hibernate.Session;
5import org.hibernate.Transaction;
6import org.hibernate.cfg.Configuration;
7
8
9public class HibernateSessionFactory {
10
11
12 private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
13
14 private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
15
16 private static final ThreadLocal<Transaction> trThreadLocal = new ThreadLocal<Transaction>();
17
18 private static Configuration configuration = new Configuration();
19
20 private static org.hibernate.SessionFactory sessionFactory;
21
22 private static String configFile = CONFIG_FILE_LOCATION;
23
24 static {
25 try {
26 configuration.configure(configFile);
27 sessionFactory = configuration.buildSessionFactory();
28 } catch (Exception e) {
29 System.err.println("%%%% Error Creating SessionFactory %%%%");
30 e.printStackTrace();
31 }
32 }
33
34 private HibernateSessionFactory() {
35 }
36
37 /** *//**
38 * Returns the ThreadLocal Session instance. Lazy initialize the
39 * <code>SessionFactory</code> if needed.
40 *
41 * @return Session
42 * @throws HibernateException
43 */
44 public static Session getSession() throws HibernateException {
45 Session session = (Session) threadLocal.get();
46
47 if (session == null || !session.isOpen()) {
48 if (sessionFactory == null) {
49 rebuildSessionFactory();
50 }
51 session = (sessionFactory != null) ? sessionFactory.openSession()
52 : null;
53 threadLocal.set(session);
54 }
55
56 return session;
57 }
58
59 /** *//**
60 * Rebuild hibernate session factory
61 *
62 */
63 public static void rebuildSessionFactory() {
64 try {
65 configuration.configure(configFile);
66 sessionFactory = configuration.buildSessionFactory();
67 } catch (Exception e) {
68 System.err.println("%%%% Error Creating SessionFactory %%%%");
69 e.printStackTrace();
70 }
71 }
72
73 /** *//**
74 * Close the single hibernate session instance.
75 *
76 * @throws HibernateException
77 */
78 public static void closeSession() throws HibernateException {
79 Session session = (Session) threadLocal.get();
80 threadLocal.set(null);
81
82 if (session != null) {
83 session.close();
84 }
85 }
86
87 /** *//**
88 * return session factory
89 *
90 */
91 public static org.hibernate.SessionFactory getSessionFactory() {
92 return sessionFactory;
93 }
94
95 /** *//**
96 * return session factory
97 *
98 * session factory will be rebuilded in the next call
99 */
100 public static void setConfigFile(String configFile) {
101 HibernateSessionFactory.configFile = configFile;
102 sessionFactory = null;
103 }
104
105 /** *//**
106 * return hibernate configuration
107 *
108 */
109 public static Configuration getConfiguration() {
110 return configuration;
111 }
112
113 public static void openTransaction() {
114 Transaction tr = trThreadLocal.get();
115 if (tr == null) {
116 tr = getSession().beginTransaction();
117 System.out.println("BeginTransaction");
118 trThreadLocal.set(tr);
119 }
120 }
121
122 public static void commitTransaction() {
123 Transaction tr = trThreadLocal.get();
124 if (tr != null && !tr.wasCommitted() && !tr.wasRolledBack()) {
125 System.out.println("Commit !");
126 tr.commit();
127 trThreadLocal.set(null);
128 }
129 }
130
131 public static void RollbackTransaction() {
132 Transaction tr = trThreadLocal.get();
133 if (tr != null && !tr.wasCommitted() && !tr.wasRolledBack()) {
134 tr.rollback();
135 System.out.println("Rollback!");
136 trThreadLocal.set(null);
137 }
138 }
139
140}
注意最後面的三個方法和trThreadLocal的屬性;
再寫一個過濾器, 代碼如下 :
org.dj.filter.HibernateSessionFilter
2
3import java.io.IOException;
4
5import javax.servlet.Filter;
6import javax.servlet.FilterChain;
7import javax.servlet.FilterConfig;
8import javax.servlet.ServletException;
9import javax.servlet.ServletRequest;
10import javax.servlet.ServletResponse;
11
12import org.dj.util.HibernateSessionFactory;
13
14public class HibernateSessionFilter implements Filter {
15
16 public void destroy() {
17 // TODO Auto-generated method stub
18
19 }
20
21 public void doFilter(ServletRequest request, ServletResponse response,
22 FilterChain chain) throws IOException, ServletException {
23
24 HibernateSessionFactory.getSession();
25 HibernateSessionFactory.openTransaction();
26 try {
27 chain.doFilter(request, response);
28 HibernateSessionFactory.commitTransaction();
29 } catch (Exception e) {
30 HibernateSessionFactory.RollbackTransaction();
31 e.printStackTrace();
32 } finally {
33 HibernateSessionFactory.closeSession();
34 }
35 }
36
37 public void init(FilterConfig filterConfig) throws ServletException {
38 // TODO Auto-generated method stub
39
40 }
41
42}
43
並在web.xml裏面配置這個過濾器,代碼如下 :
2 <filter-name>sessionFilter</filter-name>
3 <filter-class>org.dj.filter.HibernateSessionFilter</filter-class>
4 </filter>
5 <filter-mapping>
6 <filter-name>sessionFilter</filter-name>
7 <url-pattern>/*</url-pattern>
8 </filter-mapping>
這樣,我們就寫好了. 再回過頭把我在EmplyeeDao對象裏面註釋重新註釋上.並寫個兩個jsp和一個Serlvet進行測試.代碼如下:
index.jsp:
2<%
3 String path = request.getContextPath();
4 String basePath = request.getScheme() + "://"
5 + request.getServerName() + ":" + request.getServerPort()
6 + path + "/";
7%>
8
9<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
10<html>
11 <head>
12 <base href="<%=basePath%>">
13
14 <title>My JSP 'index.jsp' starting page</title>
15 <meta http-equiv="pragma" content="no-cache">
16 <meta http-equiv="cache-control" content="no-cache">
17 <meta http-equiv="expires" content="0">
18 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
19 <meta http-equiv="description" content="This is my page">
20 <!--
21 <link rel="stylesheet" type="text/css" href="styles.css">
22 -->
23 </head>
24
25 <body>
26 <form action="/DJ_HIBERNATE/servlet/GetOnlineDays">
27 員工編號:
28 <input name="eid">
29 <input type="submit">
30 </form>
31
32
33 </body>
34</html>
35
disp.jsp:
2<%
3String path = request.getContextPath();
4String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
5%>
6
7<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
8<html>
9 <head>
10 <base href="<%=basePath%>">
11
12 <title>My JSP 'disp.jsp' starting page</title>
13
14 <meta http-equiv="pragma" content="no-cache">
15 <meta http-equiv="cache-control" content="no-cache">
16 <meta http-equiv="expires" content="0">
17 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
18 <meta http-equiv="description" content="This is my page">
19 <!--
20 <link rel="stylesheet" type="text/css" href="styles.css">
21 -->
22
23 </head>
24
25 <body>
26 ${day }
27 </body>
28</html>
29
org.dj.servlet.GetOnlineDays的serlvet的代碼如果:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dj.service.EmplyeeManegerService;
public class GetOnlineDays extends HttpServlet {
private EmplyeeManegerService service = new EmplyeeManegerService();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Integer eid = Integer.parseInt(request.getParameter("eid"));
Long day = service.loadEmplyeeOnlineTime(eid);
request.setAttribute("day", day);
request.getRequestDispatcher("/disp.jsp").forward(request, response);
}
}
好了. 讓我們發佈後測試一下吧.
你會發現session was close的異常沒有了.
基本的工作原理如下 圖.