Chinasb's Blog
首页
Google App Engine
Ralasafe
开发手册
Spring注解大全
OFC2
NoSQL实战
蚂蚁运动
Browsing: / Home / 2011 / 六月 / spring2.5整合hibernate3.3的泛型Dao并加入spring jdbc的支持
Print Email Shortlink
spring2.5整合hibernate3.3的泛型Dao并加入spring jdbc的支持
BY ETHAN ON 2011 年 06 月 01 日 IN JAVA
原文链接:http://blog.csdn.net/tom_221x/archive/2009/08/22/4473873.aspx
以前写的一个改进版泛型dao,在这里 。基本实现了0代码编写dao。现在又加入了spring jdbc的支持,使得dao即可以用实体对象进行数据存取,有可以用jdbc的底层化操作删除,更新。结构见图:
具体代码和上图对应:
DaoTest.java
01
package com.test;
02
import javax.annotation.Resource;
03
import org.junit.Test;
04
import org.junit.runner.RunWith;
05
import org.springframework.test.context.ContextConfiguration;
06
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
07
import com.hibernate.entityclass.Daotest;
08
import com.tinylight.dao.base.IBaseDao;
09
@RunWith(SpringJUnit4ClassRunner.class)
10
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
11
public class DaoTest {
12
13
@Resource(name="demoDao")
14
private IBaseDao<Daotest,Integer> demoDao;
15
16
@Test
17
public void test(){
18
19
}
20
}
BaseDao.java
001
/**
002
*
003
*/
004
package com.tinylight.dao.base;
005
import java.io.Serializable;
006
import java.util.Iterator;
007
import java.util.List;
008
import org.hibernate.Query;
009
import org.hibernate.SQLQuery;
010
import org.hibernate.Session;
011
import org.hibernate.StatelessSession;
012
import org.springframework.orm.hibernate3.HibernateTemplate;
013
import com.tinylight.dao.hibernate.GenericDao;
014
import com.tinylight.dao.hibernate.GenericEntityDao;
015
import com.tinylight.dao.jdbc.SimpleJdbcDao;
016
import com.tinylight.dao.support.Page;
017
/**
018
* @author scott.Cgi
019
* @since 2009-5-12
020
* 提供dao的所有操作<br>
021
* 实现类由spring注入:<br>
022
* {@link com.tinylight.dao.hibernate.GenericEntityDao}
023
* {@link com.tinylight.dao.hibernate.GenericDao}
024
* {@link com.tinylight.dao.jdbc.SimpleJdbcDao}
025
*/
026
public class BaseDao<T,PK extends Serializable> implements IBaseDao<T,PK>{
027
protected Class<T> entityClass;// DAO所管理的Entity类型.
028
private GenericEntityDao<T,PK> gedao;
029
private GenericDao gdao;
030
private SimpleJdbcDao sjdao;
031
032
public Class<T> getEntityClass() {return entityClass;}
033
public void setEntityClass(Class<T> entityClass) {this.entityClass = entityClass;}
034
035
public GenericEntityDao<T, PK> getGedao() {return gedao;}
036
public void setGedao(GenericEntityDao<T, PK> gedao) {this.gedao = gedao;}
037
038
public GenericDao getGdao() {return gdao;}
039
public void setGdao(GenericDao gdao) {this.gdao = gdao;}
040
041
public SimpleJdbcDao getSjdao() {return sjdao;}
042
public void setSjdao(SimpleJdbcDao sjdao) {this.sjdao = sjdao;}
043
/**
044
*让spring提供构造函数注入
045
*/
046
public BaseDao(Class<T> type) {
047
this.entityClass = type;
048
}
049
050
public BaseDao(){}
051
052
public void clear() {
053
gdao.clear();
054
}
055
056
public Query createQuery(String hql, Object... values) {
057
return gdao.createQuery(hql, values);
058
}
059
060
public void delete(T entityObject) {
061
gedao.delete(entityObject);
062
}
063
064
public void deleteById(PK id) {
065
gedao.deleteById(id);
066
}
067
068
public void evict(T entityObject) {
069
gedao.evict(entityObject);
070
}
071
072
public List<T> find(String hql, Object... values) {
073
return gdao.find(hql, values);
074
}
075
076
public List<T> findByNamedParams(String hql, String[] paramNames,
077
Object... values) {
078
return gdao.findByNamedParams(hql, paramNames, values);
079
}
080
081
public void flush() {
082
gdao.flush();
083
}
084
085
public List<T> getAll() {
086
return gedao.getAll();
087
}
088
089
public T getById(PK id) {
090
return gedao.getById(id);
091
}
092
093
public Session getNativeHibernateSession() {
094
return gdao.getNativeHibernateSession();
095
}
096
097
public StatelessSession getNativeStatelessHibernateSession() {
098
return gdao.getNativeStatelessHibernateSession();
099
}
100
101
public HibernateTemplate getSpringHibernateTemplate() {
102
return gdao.getSpringHibernateTemplate();
103
}
104
105
public Iterator<T> iterator(String hql, Object... values) {
106
return gdao.iterator(hql, values);
107
}
108
109
public SimpleJdbcDao jdbc() {
110
return sjdao;
111
}
112
113
public T load(PK id) {
114
return gedao.load(id);
115
}
116
117
public void load(T entityObject, PK id) {
118
gedao.load(entityObject, id);
119
}
120
121
public T merge(T entityObject) {
122
return gedao.merge(entityObject);
123
}
124
125
public SQLQuery nativeSqlQuery(String sql) {
126
return gdao.nativeSqlQuery(sql);
127
}
128
129
public Page<T> pagedQuery(String countHql,String hql, int pageNo, int pageSize,
130
Object... values) {
131
return gdao.pagedQuery(countHql,hql, pageNo, pageSize, values);
132
}
133
134
public Page<T> pagedQueryByStartNo(String countHql,String hql, int startNo, int pageSize,
135
Object... values) {
136
return gdao.pagedQueryByStartNo(countHql,hql, startNo, pageSize, values);
137
}
138
139
public void refresh(T entityObject) {
140
gedao.refresh(entityObject);
141
}
142
143
public void save(T entityObject) {
144
gedao.save(entityObject);
145
}
146
147
}
IBaseDao.java
001
/**
002
*
003
*/
004
package com.tinylight.dao.base;
005
import java.io.Serializable;
006
import java.util.Iterator;
007
import java.util.List;
008
import org.hibernate.Query;
009
import org.hibernate.SQLQuery;
010
import org.hibernate.Session;
011
import org.hibernate.StatelessSession;
012
import org.springframework.orm.hibernate3.HibernateTemplate;
013
import com.tinylight.dao.jdbc.SimpleJdbcDao;
014
import com.tinylight.dao.support.Page;
015
/**
016
* @author scott.Cgi
017
* @since 2009-5-12
018
*
019
*/
020
public interface IBaseDao<T,PK extends Serializable> {
021
/**
022
* 根据主键类型的id获取实体对象,立即执行查询返回对象,数据库没有匹配则返回null
023
*/
024
public T getById(PK id);
025
026
/**
027
* 获取实体类型的全部对象
028
*/
029
public List<T> getAll();
030
031
/**
032
* 获取实体对象的代理,如果数据库没有匹配则异常,实体类有关联其它对象则延时加载
033
* @param id
034
* @return
035
*/
036
public T load(PK id);
037
038
/**
039
* 把数据加载到指定的非持久化实例上
040
* @param entityObject
041
* @param id
042
*/
043
public void load(T entityObject,PK id);
044
045
/**
046
* 删除对象.
047
*/
048
public void delete(T entityObject);
049
050
/**
051
* 根据id删除对象
052
* @param id
053
*/
054
public void deleteById(PK id);
055
056
/**
057
* 强迫装载对象和它的集合,使用了触发器的数据字段比较适合使用
058
* @param entityObject
059
*/
060
public void refresh(T entityObject);
061
062
/**
063
* 消除与 Hibernate Session 的关联
064
* @param entityObject
065
*/
066
public void evict(T entityObject);
067
068
/**
069
* 保存对象.<br>
070
* 如果对象已在本session中持久化了,不做任何事。<br>
071
* 如果另一个seesion拥有相同的持久化标识,抛出异常。<br>
072
* 如果没有持久化标识属性,调用save()。<br>
073
* 如果持久化标识表明是一个新的实例化对象,调用save()。<br>
074
* 如果是附带版本信息的(version或timestamp)且版本属性表明为新的实例化对象就save()。<br>
075
* 否则调用update()重新关联托管对象
076
* @param entityObject
077
*/
078
public void save(T entityObject);
079
080
/**
081
* 如果对象已在本session中持久化了,覆盖原有的<br>
082
* 如果session中没有对应对象,从数据库加载<br>
083
* 如果是脱管对象,则什么都不做
084
* @param entityObject
085
* @return
086
*/
087
public T merge(T entityObject);
088
089
/**
090
* 根据hql查询,直接使用HibernateTemplate的find函数.
091
* @param <T>
092
* @param hql
093
* @param values
094
* @return
095
*/
096
public List<T> find(String hql, Object... values);
097
098
/**
099
* 根据命名参数查询
100
* @param <T>
101
* @param hql 带有命名参数的hql语句
102
* @param paramNames 命名参数的名字
103
* @param values 命名参数的值<br>
104
* <b>例如:</b><br>
105
* findByNamedParams("from Test where t1 = :t",new String[]{"t"},tValue);
106
* @return
107
*/
108
public List<T> findByNamedParams(String hql,String[] paramNames,Object...values);
109
110
/**
111
* 创建Query对象.<br>
112
* 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
113
* @param hql
114
* @param values
115
* @return
116
*/
117
public Query createQuery(String hql,Object... values);
118
119
/**
120
* 执行一些必须的sql语句把内存中的对象同步到数据库中
121
*/
122
public void flush();
123
124
/**
125
* 清除对象缓存
126
*/
127
public void clear();
128
129
/**
130
* 返回iterator接口类型的结果
131
* @param <T>
132
* @param hql
133
* @param values
134
* @return
135
*/
136
public Iterator<T> iterator(String hql,Object...values);
137
138
/**
139
* @return 当前上下文的原生Hibernate session对象,依然受到spring事务管理不需要手动close
140
*/
141
public Session getNativeHibernateSession();
142
143
/**
144
* @return 当前上下文的原生Hibernate StatelessSession对象<br>
145
* 此对象不级联关联实例,忽略集合不触发Hibernate事件模型和拦截器,没有一级缓存,没有持久化上下文,接近JDBC.
146
*/
147
public StatelessSession getNativeStatelessHibernateSession();
148
149
/**
150
* 执行本地查询获得SQLQuery对象<br>
151
* 可以调用addEntity(*.class).list();获得对应实体list集合<br>
152
* addEntity.add(*.class).addJoin(*.class).list();获得一对多代理对象<br>
153
* 更多用法见google
154
* @param sql
155
* @return
156
*/
157
public SQLQuery nativeSqlQuery(String sql);
158
159
/**
160
* @param <T>
161
* @param countHql 计算数据总条数的hql语句(就是带count(*)的hql)
162
* @param hql
163
* @param pageNo 页面号
164
* @param pageSize 页面容量
165
* @param values
166
* @return
167
*/
168
public Page<T> pagedQuery(String countHql,String hql, int pageNo, int pageSize, Object... values);
169
170
/**
171
* @param <T>
172
* @param countHql 计算数据总条数的hql语句(就是带count(*)的hql)
173
* @param hql
174
* @param startNo 分页从哪一条数据开始
175
* @param pageSize 页面容量
176
* @param values
177
* @return
178
*/
179
public Page<T> pagedQueryByStartNo(String countHql,String hql, int startNo, int pageSize, Object... values);
180
181
/**
182
* @return 获得spring的HibernateTemplate拥有更多的功能
183
*/
184
public HibernateTemplate getSpringHibernateTemplate();
185
186
/**
187
* @return 获得jdbc操作的超绚酷dao
188
*/
189
public SimpleJdbcDao jdbc();
190
}
GenericDao.java
001
/**
002
*
003
*/
004
package com.tinylight.dao.hibernate;
005
import java.util.Iterator;
006
import java.util.List;
007
import org.hibernate.Query;
008
import org.hibernate.SQLQuery;
009
import org.hibernate.Session;
010
import org.hibernate.StatelessSession;
011
import org.springframework.orm.hibernate3.HibernateTemplate;
012
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
013
import com.tinylight.dao.support.Page;
014
/**
015
* 继承自spring的HibernateDaoSupport<br>
016
* 提供了和具体实体类无关的数据库操作
017
* @author scott.Cgi
018
* @since 2009-5-10
019
*
020
*/
021
public class GenericDao extends HibernateDaoSupport {
022
023
/**
024
* 根据hql查询,直接使用HibernateTemplate的find函数.
025
* @param <T>
026
* @param hql
027
* @param values
028
* @return
029
*/
030
@SuppressWarnings("unchecked")
031
public <T> List<T> find(String hql, Object... values) {
032
return this.getHibernateTemplate().find(hql, values);
033
}
034
035
/**
036
* 根据命名参数查询
037
* @param <T>
038
* @param hql 带有命名参数的hql语句
039
* @param paramNames 命名参数的名字
040
* @param values 命名参数的值<br>
041
* <b>例如:</b><br>
042
* findByNamedParams("from Test where t1 = :t",new String[]{"t"},tValue);
043
* @return
044
*/
045
@SuppressWarnings("unchecked")
046
public <T> List<T> findByNamedParams(String hql,String[] paramNames,Object...values){
047
return this.getHibernateTemplate().findByNamedParam(hql, paramNames, values);
048
}
049
050
/**
051
* 创建Query对象.<br>
052
* 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
053
* @param hql
054
* @param values
055
* @return
056
*/
057
public Query createQuery(String hql,Object... values) {
058
//这里的false表示不创建session保证,当前操作在spring同一个事务的管理下
059
Query query = this.getSession(false).createQuery(hql);
060
if (values != null) {
061
for (int i = 0; i < values.length; i++) {
062
query.setParameter(i, values[i]);
063
}
064
}
065
return query;
066
}
067
068
/**
069
* 执行一些必须的sql语句把内存中的对象同步到数据库中
070
*/
071
public void flush() {
072
this.getHibernateTemplate().flush();
073
}
074
075
/**
076
* 清除对象缓存
077
*/
078
public void clear() {
079
this.getHibernateTemplate().clear();
080
}
081
082
/**
083
* 返回iterator接口类型的结果
084
* @param <T>
085
* @param hql
086
* @param values
087
* @return
088
*/
089
@SuppressWarnings("unchecked")
090
public <T> Iterator<T> iterator(String hql,Object...values){
091
return this.getHibernateTemplate().iterate(hql, values);
092
}
093
094
/**
095
* @return 当前上下文的原生Hibernate session对象,依然受到spring事务管理不需要手动close
096
*/
097
public Session getNativeHibernateSession(){
098
return this.getSessionFactory().getCurrentSession();
099
}
100
101
/**
102
* @return 当前上下文的原生Hibernate StatelessSession对象<br>
103
* 此对象不级联关联实例,忽略集合不触发Hibernate事件模型和拦截器,没有一级缓存,没有持久化上下文,接近JDBC.
104
*/
105
public StatelessSession getNativeStatelessHibernateSession(){
106
return this.getSessionFactory().openStatelessSession();
107
}
108
109
/**
110
* 执行本地查询获得SQLQuery对象<br>
111
* 可以调用addEntity(*.class).list();获得对应实体list集合<br>
112
* addEntity.add(*.class).addJoin(*.class).list();获得一对多代理对象<br>
113
* 更多用法见google
114
* @param sql
115
* @return
116
*/
117
public SQLQuery nativeSqlQuery(String sql){
118
return this.getSession(false).createSQLQuery(sql);
119
}
120
121
/**
122
* @param <T>
123
* @param countHql 计算数据总条数的hql语句(就是带count(*)的hql)
124
* @param hql
125
* @param pageNo 页面号
126
* @param pageSize 页面容量
127
* @param values
128
* @return
129
*/
130
@SuppressWarnings("unchecked")
131
public <T> Page<T> pagedQuery(String countHql,String hql, int pageNo, int pageSize, Object... values) {
132
// Count查询
133
List<T> countlist = this.getHibernateTemplate().find(countHql, values);
134
long totalCount = (Long) countlist.get(0);
135
if (totalCount < 1)
136
return new Page<T>();
137
// 当前页的开始数据索引
138
long startIndex = Page.getStartOfPage(pageNo, pageSize);
139
Query query = this.createQuery(hql, values);
140
List<T> list = query.setFirstResult((int) startIndex).setMaxResults(pageSize).list();
141
return new Page<T>(startIndex, totalCount, pageSize, list);
142
}
143
144
/**
145
* @param <T>
146
* @param countHql 计算数据总条数的hql语句(就是带count(*)的hql)
147
* @param hql
148
* @param startNo 分页从哪一条数据开始
149
* @param pageSize 页面容量
150
* @param values
151
* @return
152
*/
153
@SuppressWarnings("unchecked")
154
public <T> Page<T> pagedQueryByStartNo(String countHql,String hql, int startNo, int pageSize, Object... values){
155
// Count查询
156
List<T> countlist = getHibernateTemplate().find(countHql, values);
157
long totalCount = (Long) countlist.get(0);
158
if (totalCount < 1)
159
return new Page();
160
161
int startIndex = startNo;
162
Query query = createQuery(hql, values);
163
List<T> list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
164
return new Page<T>(startIndex, totalCount, pageSize, list);
165
}
166
167
/**
168
* @return 获得spring的HibernateTemplate拥有更多的功能
169
*/
170
public HibernateTemplate getSpringHibernateTemplate(){
171
return this.getHibernateTemplate();
172
}
173
}
GenericEntityDao.java
view sourceprint?
001
/**
002
*
003
*/
004
package com.tinylight.dao.hibernate;
005
import java.io.Serializable;
006
import java.util.List;
007
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
008
/**
009
* 负责为单个Entity对象提供CRUD操作的Hibernate DAO基类.<br>
010
* 子类只要在类定义时指定所管理Entity的Class<br>
011
* 即拥有对单个Entity对象的CRUD操作.
012
* @author scott.Cgi
013
* @since 2009-5-11
014
*
015
*/
016
public class GenericEntityDao<T,PK extends Serializable> extends HibernateDaoSupport {
017
018
protected Class<T> entityClass;// DAO所管理的Entity类型.
019
public void setEntityClass(Class<T> type){//注入实体类型
020
this.entityClass=type;
021
}
022
public Class<T> getEntityClass(){
023
return this.entityClass;
024
}
025
026
public GenericEntityDao(){}
027
public GenericEntityDao(Class<T> entityClass){this.entityClass = entityClass;}
028
/**
029
* 根据主键类型的id获取实体对象,立即执行查询返回对象,数据库没有匹配则返回null
030
*/
031
@SuppressWarnings("unchecked")
032
public T getById(PK id) {
033
return (T)this.getHibernateTemplate().get(this.entityClass, id);
034
}
035
036
/**
037
* 获取实体类型的全部对象
038
*/
039
@SuppressWarnings("unchecked")
040
public List<T> getAll() {
041
return (List<T>)(this.getHibernateTemplate().loadAll(this.entityClass));
042
}
043
044
/**
045
* 获取实体对象的代理,如果数据库没有匹配则异常,实体类有关联其它对象则延时加载
046
* @param id
047
* @return
048
*/
049
@SuppressWarnings("unchecked")
050
public T load(PK id){
051
return (T)this.getHibernateTemplate().load(this.entityClass, id);
052
}
053
054
/**
055
* 把数据加载到指定的非持久化实例上
056
* @param entityObject
057
* @param id
058
*/
059
public void load(T entityObject,PK id){
060
this.getHibernateTemplate().load(entityObject, id);
061
}
062
063
/**
064
* 删除对象.
065
*/
066
public void delete(T entityObject) {
067
this.getHibernateTemplate().delete(entityObject);
068
}
069
070
/**
071
* 根据id删除对象
072
* @param id
073
*/
074
public void deleteById(PK id){
075
this.delete(this.getById(id));
076
}
077
078
/**
079
* 强迫装载对象和它的集合,使用了触发器的数据字段比较适合使用
080
* @param entityObject
081
*/
082
public void refresh(T entityObject){
083
this.getHibernateTemplate().refresh(entityObject);
084
}
085
086
/**
087
* 消除与 Hibernate Session 的关联
088
* @param entityObject
089
*/
090
public void evict(T entityObject){
091
this.getHibernateTemplate().evict(entityObject);
092
}
093
094
/**
095
* 保存对象.<br>
096
* 如果对象已在本session中持久化了,不做任何事。<br>
097
* 如果另一个seesion拥有相同的持久化标识,抛出异常。<br>
098
* 如果没有持久化标识属性,调用save()。<br>
099
* 如果持久化标识表明是一个新的实例化对象,调用save()。<br>
100
* 如果是附带版本信息的(version或timestamp)且版本属性表明为新的实例化对象就save()。<br>
101
* 否则调用update()重新关联托管对象
102
* @param entityObject
103
*/
104
public void save(T entityObject){
105
this.getHibernateTemplate().saveOrUpdate(entityObject);
106
}
107
108
/**
109
* 如果对象已在本session中持久化了,覆盖原有的<br>
110
* 如果session中没有对应对象,从数据库加载<br>
111
* 如果是脱管对象,则什么都不做
112
* @param entityObject
113
* @return
114
*/
115
@SuppressWarnings("unchecked")
116
public T merge(T entityObject){
117
return (T)this.getHibernateTemplate().merge(entityObject);
118
}
119
120
}
SimpleJdbcDao.java
001
/**
002
*
003
*/
004
package com.tinylight.dao.jdbc;
005
import java.sql.Connection;
006
import java.sql.SQLException;
007
import org.springframework.jdbc.core.JdbcTemplate;
008
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
009
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
010
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
011
import org.springframework.jdbc.datasource.DataSourceUtils;
012
import org.springframework.jdbc.support.GeneratedKeyHolder;
013
import org.springframework.jdbc.support.KeyHolder;
014
import org.springframework.jdbc.support.rowset.SqlRowSet;
015
/**
016
* 继承spring的SimpleJdbcDaoSupport
017
* 提供对数据库jdbc级别的操作
018
* 内部使用spring的SimpleJdbcTemplate与JdbcTemplate
019
* @author scott.Cgi
020
* @since 2009-5-7
021
*/
022
public class SimpleJdbcDao extends SimpleJdbcDaoSupport {
023
024
/**
025
* 提供对表的更改和删除操作
026
* @param sql 要执行的sql语句
027
* @param args 变参
028
* @return 影响的行数
029
*/
030
public int update(String sql,Object...args){
031
return this.getSimpleJdbcTemplate().update(sql, args);
032
}
033
034
/**
035
* 批量更新多条记录
036
* @param sql 多条sql组成的数组(不带参数的)
037
* @see 带参数的见: <br>
038
* getJdbcTemplate().batchUpdate(String[] sql,BatchPreparedStatementSetter pss)
039
* @return 影响行数数组
040
*/
041
public int[] batchUpdate(String[] sql){
042
return this.getJdbcTemplate().batchUpdate(sql);
043
}
044
045
/**
046
* 获取行数
047
* @param countSql 计算行数的sql语句
048
* @return
049
*/
050
public long countRows(String countSql){
051
return this.getJdbcTemplate().queryForLong(countSql);
052
}
053
054
/**
055
* 获取本地的Connection对象
056
* @return
057
*/
058
public Connection getNativeConn(){
059
060
//从当前线程绑定的数据连接获取连接
061
Connection conn = DataSourceUtils.getConnection(this.getJdbcTemplate().getDataSource());
062
try {
063
conn = this.getJdbcTemplate().getNativeJdbcExtractor().getNativeConnection(conn);
064
} catch (SQLException e) {
065
e.printStackTrace();
066
return null;
067
}
068
069
return conn;
070
}
071
072
/**
073
* 获得断开数据库连接的行集,大结果集会消耗内存,受到maxSize的限制
074
* @param sql 要执行的sql语句带?占位符
075
* @param params 填充占位符的数组
076
* @param types 填充参数类型(java.sql.Types中的常量)
077
* 例如:new int[]{Types.VARCHAR,Types.DATE}
078
* @return 影响的行数<br>
079
* <b>注:</b> params和types同时为空,sql为不带?占位符;仅仅types为空时,由spring去猜测类型
080
*/
081
public SqlRowSet queryForRowSet(String sql,Object[] params,int[] types){
082
083
if(params != null && types != null){
084
return this.getJdbcTemplate().queryForRowSet(sql, params, types);
085
}else if(params != null && types == null){
086
return this.getJdbcTemplate().queryForRowSet(sql, params);
087
}else {
088
return this.getJdbcTemplate().queryForRowSet(sql);
089
}
090
}
091
092
/**
093
* 提供对表的更改和删除操作
094
* @param hql 使用了命名参数的sql语句
095
* @param sps 例如:<br>
096
* new BeanPropertySqlParamterSource(javaBean其属性要和命名参数对应);<br>
097
* new MapSqlParameterSource().add("命名参数",参数对应的值).add()...可以链式调用
098
* @return KeyHolder主键持有者对象;如果是新增数据,KeyHolder持有新增的主键值<br>
099
* 有3个方法可调用:<br>getKey()一个数字主键<br>
100
* getKeys()复合主键Map结构<br>
101
* getKeyList()多个主键由多个Map组成的List
102
*/
103
public KeyHolder updateNamedParamer(String hql,SqlParameterSource sps){
104
KeyHolder keyHolder = new GeneratedKeyHolder();
105
this.getSimpleJdbcTemplate().getNamedParameterJdbcOperations().update(hql, sps, keyHolder);
106
return keyHolder;
107
}
108
109
/**
110
* 执行sql语句,如创建表等
111
* @param sql
112
*/
113
public void executeSql(String sql){
114
this.getJdbcTemplate().execute(sql);
115
}
116
117
/**
118
* @return 获得spring的JdbcTemplate使用更多功能
119
*/
120
public JdbcTemplate getSpringJdbcTemplate(){
121
return this.getJdbcTemplate();
122
}
123
124
/**
125
* 引入jdk5.0语法的JdbcTemplate的简化版本
126
* @return 获得spring的SimpleJdbcTemplate使用更多功能
127
*/
128
public SimpleJdbcTemplate getSpringSimplaJdbcTemplate(){
129
return this.getSimpleJdbcTemplate();
130
}
131
}
Page.java
001
package com.tinylight.dao.support;
002
import java.io.Serializable;
003
import java.util.Collections;
004
import java.util.List;
005
/**
006
* 分页对象.包含当前页数据及分页信息如总记录数.
007
*
008
* @author scott.Cgi
009
* @since 2008-6-29
010
*/
011
public class Page<T> implements Serializable {
012
private static final long serialVersionUID = -5624189033006412710L;
013
private static long DEFAULT_PAGE_SIZE = 20;
014
private long pageSize = DEFAULT_PAGE_SIZE; // 每页的记录数
015
private long start; // 当前页第一条数据在List中的位置,从0开始
016
private List<T> data = Collections.emptyList(); // 当前页中存放的记录
017
private long totalCount = 0; // 总记录数
018
/**
019
* 构造方法,只构造空页.
020
*/
021
public Page() {
022
this(0l, 0l, DEFAULT_PAGE_SIZE, Collections.<T>emptyList());
023
}
024
/**
025
* 默认构造方法.
026
*
027
* @param start 本页数据在数据库中的起始位置
028
* @param totalSize 数据库中总记录条数
029
* @param pageSize 本页容量
030
* @param data 本页包含的数据
031
*/
032
public Page(long start, long totalSize, long pageSize, List<T> data) {
033
this.pageSize = pageSize;
034
this.start = start;
035
this.totalCount = totalSize;
036
this.data = data;
037
}
038
/**
039
* 取总记录数.
040
*/
041
public long getTotalCount() {
042
return this.totalCount;
043
}
044
/**
045
* 取总页数.
046
*/
047
public long getTotalPageCount() {
048
if (totalCount % pageSize == 0)
049
return totalCount / pageSize;
050
else
051
return totalCount / pageSize + 1;
052
}
053
/**
054
* 取每页数据容量.
055
*/
056
public Long getPageSize() {
057
return pageSize;
058
}
059
/**
060
* 取当前页中的记录.
061
*/
062
public List<T> getResult() {
063
return data;
064
}
065
/**
066
* 取该页当前页码,页码从1开始.
067
*/
068
public long getCurrentPageNo() {
069
return start / pageSize + 1;
070
}
071
/**
072
* 该页是否有下一页.
073
*/
074
public boolean hasNextPage() {
075
return this.getCurrentPageNo() < this.getTotalPageCount();
076
}
077
/**
078
* 该页是否有上一页.
079
*/
080
public boolean hasPreviousPage() {
081
return this.getCurrentPageNo() > 1;
082
}
083
/**
084
* 获取任一页第一条数据在数据集的位置,每页条数使用默认值.
085
*
086
*/
087
protected static long getStartOfPage(long pageNo) {
088
return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE);
089
}
090
/**
091
* 获取任一页第一条数据在数据集的位置.
092
*
093
* @param pageNo 从1开始的页号
094
* @param pageSize 每页记录条数
095
* @return 该页第一条数据
096
*/
097
public static long getStartOfPage(long pageNo, long pageSize) {
098
return (pageNo - 1) * pageSize;
099
}
100
}
applicationContext-annotation.xml
01
<?xml version="1.0" encoding="UTF-8" ?>
02
<beans xmlns="http://www.springframework.org/schema/beans"
03
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
04
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
05
xmlns:context="http://www.springframework.org/schema/context"
06
xmlns:aop="http://www.springframework.org/schema/aop"
07
xsi:schemaLocation="http://www.springframework.org/schema/beans
08
09
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
10
11
http://www.springframework.org/schema/context
12
13
http://www.springframework.org/schema/context/spring-context-2.5.xsd
14
15
http://www.directwebremoting.org/schema/spring-dwr
16
17
http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd
18
19
http://www.springframework.org/schema/aop
20
21
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
22
23
<context:annotation-config/>
24
</beans>
applicationContext-list.xml
01
<?xml version="1.0" encoding="UTF-8"?>
02
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
03
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
04
xmlns:context="http://www.springframework.org/schema/context"
05
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
06
<description>导入applicationContext文件列表,可随时通过注释disable不需要的模块</description>
07
<!-- 导入spring aop配置文件 -->
08
<import resource="applicationContext-tx.xml" />
09
<!-- 导入spring dao配置文件 -->
10
<import resource="tinylight-dao.xml" />
11
12
</beans>
applicationContext-tx.xml
01
<?xml version="1.0" encoding="UTF-8"?>
02
<!-- 使用aop/tx命名空间 -->
03
<beans xmlns="http://www.springframework.org/schema/beans"
04
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
05
xmlns:aop="http://www.springframework.org/schema/aop"
06
xmlns:tx="http://www.springframework.org/schema/tx"
07
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
08
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
09
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
10
<!-- 配置事务管理器bean,使用HibernateTransactionManager事务管理器 -->
11
<bean id="txManager"
12
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
13
<!-- 为事务管理器注入sessionFactory" -->
14
<property name="sessionFactory">
15
<ref bean="sessionFactory" />
16
</property>
17
</bean>
18
<!-- 通过aop定义事务增强切面 -->
19
<aop:config>
20
<!-- 使用强大的切点表达式语言轻松定义目标方法 -->
21
<aop:pointcut id="serviceMethod"
22
expression="execution(* com.tinylight.dao.base.IBaseDao.*(..))" />
23
<!-- 引用事务增强 -->
24
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
25
</aop:config>
26
<!-- 事务增强 -->
27
<tx:advice id="txAdvice" transaction-manager="txManager">
28
<!-- 属性事务定义 -->
29
<tx:attributes>
30
<!--OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。
31
然后把该sessionFactory绑定到TransactionSynchronizationManager,使request的整个过程都使用同一个session,
32
在请求过后再接除该sessionFactory的绑定,最后closeSessionIfNecessary根据该session是否已和transaction绑定来决定是否关闭session。
33
在这个过程中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥有写权限。
34
也即是,如果有不是readOnly的transaction就可以由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操作权限,如果没有transaction,
35
并且没有另外人为地设flush model的话,则doFilter的整个过程都是Flush.NEVER。所以受transaction保护的方法有写权限,没受保护的则没有 -->
36
<tx:method name="*" />
37
</tx:attributes>
38
</tx:advice>
39
40
</beans>
applicationContext.xml
001
<?xml version="1.0" encoding="UTF-8"?>
002
<beans xmlns="http://www.springframework.org/schema/beans"
003
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
004
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
005
<!-- 使用外部文件配置数据源的属性 -->
006
<bean
007
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
008
<property name="locations">
009
<list>
010
<!-- 外部文件地址 -->
011
<value>classpath:database_conn.properties</value>
012
</list>
013
</property>
014
<property name="fileEncoding" value="utf-8" />
015
</bean>
016
<!-- 配置数据源 -->
017
<bean id="dataSource"
018
class="com.mchange.v2.c3p0.ComboPooledDataSource"
019
destroy-method="close">
020
<property name="driverClass" value="${driverClassName}" />
021
<property name="jdbcUrl" value="${url}"/>
022
<property name="user" value="${username}"/>
023
<property name="password" value="${password}"/>
024
025
<!--连接池中保留的最小连接数。-->
026
<property name="minPoolSize" value="5" />
027
028
<!--连接池中保留的最大连接数。Default: 15 -->
029
<property name="maxPoolSize" value="20" />
030
031
<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
032
<property name="initialPoolSize" value="10" />
033
034
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
035
<property name="maxIdleTime" value="60" />
036
037
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
038
<property name="acquireIncrement" value="5" />
039
040
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
041
属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
042
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
043
<property name="maxStatements" value="0"/>
044
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
045
<property name="idleConnectionTestPeriod" value="60"/>
046
047
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
048
<property name="acquireRetryAttempts" value="0" />
049
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
050
保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
051
获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->
052
<property name="breakAfterAcquireFailure" value="true" />
053
054
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
055
时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
056
等方法来提升连接测试的性能。Default: false -->
057
<property name="testConnectionOnCheckout" value="false" />
058
</bean>
059
<!-- hibernate3 sessionfactory配置
060
使用AnnotationSessionFactoryBean创建基于JPA注解的SessionFactory-->
061
<bean id="sessionFactory"
062
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
063
<!-- 引用数据源 -->
064
<property name="dataSource">
065
<ref bean="dataSource" />
066
</property>
067
<property name="namingStrategy">
068
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
069
</property>
070
<!-- hibernate的属性具体见hibernate文档 -->
071
<property name="hibernateProperties">
072
<props>
073
<prop key="hibernate.dialect">
074
org.hibernate.dialect.MySQLDialect
075
</prop>
076
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
077
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
078
<!-- 非0值 指定jdbc抓取数量的大小调用Statement.setFetchSize() -->
079
<prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>
080
<!-- jdbc批量更新 建议5到30 -->
081
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
082
<!--说明一下:如果不设置查询缓存,那么hibernate只会缓存使用load()方法获得的单个持久化对象
083
如果想缓存使用findall()、list()、Iterator()、createCriteria()、createQuery()
084
等方法获得的数据结果集的话就需要设置hibernate.cache.use_query_cache true 才行 -->
085
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
086
<prop key="hibernate.cache.provider_class">
087
org.hibernate.cache.EhCacheProvider
088
</prop>
089
<prop key="hibernate.cache.provider_configuration_file_resource_path">
090
${hibernate.ehcache_config_file}
091
</prop>
092
</props>
093
</property>
094
095
<property name="packagesToScan" value="com.hibernate.entityclass" />
096
</bean>
097
098
<!-- 加载spring功能列表文件 -->
099
<import resource="applicationContext-list.xml"/>
100
</beans>
database_conn.properties
01
#jdbc settings
02
driverClassName=org.gjt.mm.mysql.Driver
03
url=jdbc\:mysql\://127.0.0.1\:3306/mytest
04
username=root
05
password=123456
06
#hibernate settings
07
hibernate.show_sql=true
08
hibernate.format_sql=true
09
hibernate.cache.use_query_cache=false
10
hibernate.jdbc.fetch_size=10
11
hibernate.jdbc.batch_size=5
12
hibernate.ehcache_config_file=ehcache.xml
ehcache.xml
01
<ehcache>
02
<!-- Sets the path to the directory where cache .data files are created.
03
04
If the path is a Java System Property it is replaced by
05
its value in the running VM.
06
07
The following properties are translated:
08
user.home - User's home directory
09
user.dir - User's current working directory
10
java.io.tmpdir - Default temp file path -->
11
<diskStore path="java.io.tmpdir" />
12
<!--Default Cache configuration. These will applied to caches programmatically created through
13
the CacheManager.
14
15
The following attributes are required:
16
17
maxElementsInMemory - Sets the maximum number of objects that will be created in memory
18
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the
19
element is never expired.
20
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
21
has reached the maxInMemory limit.
22
23
The following attributes are optional:
24
timeToIdleSeconds - Sets the time to idle for an element before it expires.
25
i.e. The maximum amount of time between accesses before an element expires
26
Is only used if the element is not eternal.
27
Optional attribute. A value of 0 means that an Element can idle for infinity.
28
The default value is 0.
29
timeToLiveSeconds - Sets the time to live for an element before it expires.
30
i.e. The maximum time between creation time and when an element expires.
31
Is only used if the element is not eternal.
32
Optional attribute. A value of 0 means that and Element can live for infinity.
33
The default value is 0.
34
diskPersistent - Whether the disk store persists between restarts of the Virtual Machine.
35
The default value is false.
36
diskExpiryThreadIntervalSeconds- The number of seconds between runs of the disk expiry thread. The default value
37
is 120 seconds.
38
-->
39
<cache name="org.hibernate.cache.StandardQueryCache"
40
maxElementsInMemory="50"
41
eternal="false"
42
timeToIdleSeconds="3600"
43
timeToLiveSeconds="7200"
44
overflowToDisk="true" />
45
<cache name="org.hibernate.cache.UpdateTimestampsCache"
46
maxElementsInMemory="5000"
47
eternal="true"
48
overflowToDisk="true" />
49
<!--
50
默认的Cache配置。用来实现CacheManager.add(String cacheName)创建的缓存
51
memoryStoreEvictionPolicy:内存存储与释放策略。有三个值:
52
LRU -least recently used
53
LFU -least frequently used
54
FIFO-first in first out, the oldest element by creation time
55
diskPersistent :是否持久化磁盘缓存。
56
当这个属性的值为true时,系统在初始化的时候会在磁盘中查找文件名为cache名称
57
后缀名为index的的文件,如CACHE_FUNC.index
58
-->
59
<defaultCache maxElementsInMemory="10000"
60
eternal="false"
61
timeToIdleSeconds="120"
62
timeToLiveSeconds="120"
63
overflowToDisk="true"
64
diskPersistent="false"
65
diskExpiryThreadIntervalSeconds="120"
66
memoryStoreEvictionPolicy="LFU"
67
/>
68
<!-- See http://ehcache.sourceforge.net/documentation/#mozTocId258426 for how to configure caching for your objects -->
69
</ehcache>
log4j.properties
01
log4j.rootLogger=INFO, stdout, logfile
02
log4j.logger.org.springframework=WARN
03
log4j.logger.org.hibernate=WARN
04
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
05
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
06
log4j.appender.stdout.layout.ConversionPattern=[%d] %-5p \: %m%n
07
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
08
log4j.appender.logfile.File=${webAppRootKey}/superDao.log
09
log4j.appender.logfile.MaxFileSize=512KB
10
# Keep three backup files.
11
log4j.appender.logfile.MaxBackupIndex=3
12
# Pattern to output: date priority [category] - message
13
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
14
log4j.appender.logfile.layout.ConversionPattern=[%d] %p [%c] - %m%n
tinyLight-dao.xml
01
<?xml version="1.0" encoding="UTF-8"?>
02
<beans xmlns="http://www.springframework.org/schema/beans"
03
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
04
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
05
<description>tinyLight Dao配置</description>
06
<!-- 定义JdbcTemplate Bean(线程安全,执行底层sql语句) -->
07
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
08
<!-- 设置数据源 -->
09
<property name="dataSource" ref="dataSource" />
10
<!-- 设置jdbcTemplate创建的statement查询数据时最大的超时时间,默认0 -->
11
<property name="queryTimeout" value="0" />
12
<!-- 设置底层ResultSet每次从数据库返回的行数,默认0,Oracle默认100 -->
13
<property name="fetchSize" value="0" />
14
<!-- 设置底层ResultSet从数据库返回的最大行数,默认0 -->
15
<property name="maxRows" value="0" />
16
<!-- 是否忽略sql警告信息,默认true,false JdbcTemplate将会抛出SQLWarningException -->
17
<property name="ignoreWarnings" value="true" />
18
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor" />
19
</bean>
20
<!-- 定义DBCP数据源的JDBC本地对象抽取器 -->
21
<bean id="nativeJdbcExtractor" lazy-init="true"
22
class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" />
23
<!-- 定义封装了jdbc操作数据的dao -->
24
<bean id="simpleJdbcDao" class="com.tinylight.dao.jdbc.SimpleJdbcDao">
25
<property name="jdbcTemplate" ref="jdbcTemplate" />
26
</bean>
27
<!-- 定义了与实体相关的dao -->
28
<bean id="genericEntityDao" class="com.tinylight.dao.hibernate.GenericEntityDao"
29
scope="prototype" lazy-init="true">
30
<property name="sessionFactory">
31
<ref bean="sessionFactory" />
32
</property>
33
</bean>
34
<!-- 定义了与实体无关的dao -->
35
<bean id="genericDao" class="com.tinylight.dao.hibernate.GenericDao">
36
<property name="sessionFactory">
37
<ref bean="sessionFactory" />
38
</property>
39
</bean>
40
<!--使用泛型DAO作为抽象基类-->
41
<bean id="baseDao" class="com.tinylight.dao.base.BaseDao"
42
abstract="true" depends-on="genericEntityDao,genericDao">
43
<property name="gedao">
44
<ref bean="genericEntityDao" />
45
</property>
46
<property name="gdao">
47
<ref bean="genericDao" />
48
</property>
49
<property name="sjdao">
50
<ref bean="simpleJdbcDao"/>
51
</property>
52
</bean>
53
<!--
54
当然这里也可以不必为每一个实体类的配置像下面这样的代码,
55
那就要在spring注解注入dao到service类的时候,加上下面这个方法:
56
/**
57
* spring bean的后处理器,如果子类是spring初始化的bean,则在初始化后设置注解dao的实体类类型
58
* @throws IllegalArgumentException
59
* @throws IllegalAccessException
60
*/
61
@PostConstruct
62
@SuppressWarnings("unchecked")
63
protected void preparedDao() throws IllegalArgumentException, IllegalAccessException{
64
Class<? extends BaseService> cl = this.getClass();
65
for(Field f : cl.getDeclaredFields()){
66
log.info("Service类注解属性名称 = {},类型 = {}",f.getName(),f.getGenericType());
67
if(f.isAnnotationPresent(Resource.class) && f.getAnnotation(Resource.class).name().equals("baseDao")){
68
f.setAccessible(true);//修改private修饰权限
69
Type[] params = ((ParameterizedType)f.getGenericType()).getActualTypeArguments();
70
log.info("实体类的参数类型 = {}",params[0].toString());
71
((IBaseDao<?,?>)f.get(this)).changeEntityClass((Class)params[0]);//设置实体类类型
72
f.setAccessible(false);//恢复private修饰权限
73
}
74
}
75
}
76
这样就可以为每一个实体类加下面这段xml配置了,当然dao是不在学要写一条代码啦
77
-->
78
79
<!-- 配置实体Demodata的DAO -->
80
<bean id="demoDao" parent="baseDao">
81
<constructor-arg>
82
<value>com.hibernate.entityclass.Daotest</value>
83
</constructor-arg>
84
</bean>
85
86
</beans>
这个svn有源代码,有兴趣可以看看.
http://xeducation.googlecode.com/svn/trunk
是myeclipse的工程
Share this on: Mixx Delicious Digg Facebook Twitter
DAOHibernateJDBCSpring
Related StoriesMost Popular
Linux系统信息查看命令大全
MySQL架构方案
Struts2 注解功能
Struts2 零配置方法总结
Spring与Memcache的集成
Apache Mina ProtocolCodecFilter Introduction
Leave a Reply
Name *
Email *
Website
Comment
有人回复时邮件通知我