本框架内容已在多项目中使用,可以实现数据的持久化操作及数据实体查询.目前只适用于ORACLE数据库
持久化
通过自定义的Annotation实现Bean数据到SQL语句的转换.
本框架用到两个自定义的Annotation--AnnEntity和AnnDbField,分别用来标注Bean所对应的表信息和字段信息.要进行POJO操作的Bean必须使用这两个标注类进行修饰
package test.springmvc;
import cn.jacore.annotation.AnnDbField;
import cn.jacore.annotation.AnnEntity;
@AnnEntity(tablename = "TEST_TESTTABLE", pktype = AnnEntity.SEQUENCE,sequence="TEST_SEQ")
public class TestTable {
@AnnDbField
private Long nid;
@AnnDbField(columnname="testTable_content")
private String content;
public Long getNid() {
return nid;
}
public void setNid(Long nid) {
this.nid = nid;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
AnnEntity的参数
tablename : 指定此Bean对应的数据库表名字
pktype : 指定主键类型支持4种类型,其中SEQUENCE和UUID可在持久化时自动生成;ASSIGNED使用用户自己生成的主键值;NONE无主键
sequence : 如果指定使用SEQUENCE必须再指定数据库中sequence的名称
AnnDbField的参数
columnname : 此属性对应的数据库表中的字段名字,如果属性名与字段名相同(不区分大小写)此项可以忽略.
当保存数据时本框架只把AnnDbField修饰的属性进行持久化操作,实体查询时默认也只给修饰的属性赋值,同时也提供根据查询返回字段名进行赋值的方法.
实体类设置完成
DAO操作
使用本框架进行持久化操作的DAO类要继承框架中封装的AbstractJdbcBaseDao并调用saveOrUpdate(Object obj)方法.此方法返回持久化后的Bean.持久化时判断使用INSERT还是UPDATE使用了最简单的方法,即查看主键是否有值,如果不为空执行UPDATE否则INSERT,对业务逻辑有严格要求的不要使用本框架了.
实体查询
通过实现ResultSetExtractor和RowMapper接口实现数据的实体查询
EntityMappingTool
实现了ResultSetExtractor接口,可以把查询的返回单条数据赋值给一个Bean对象.
继承AbstractJdbcBaseDao的DAO类调用queryForEntity(String sql,Object[]param,Class entity)方法可以得到查询返回的实体类
参数说明:
@param sql 查询语句
@param param 查询参数
@param entity 返回的实体类型
如果查询返回结果中的某一字段在Bean中有对应属性但没有用AnnDbField修饰,那要给这类属性赋值的话先调用super.entityMapping.setSeeRs(true)再执行queryForEntity
RowMappingTool
实现RowMapper接口,用于多条记录的实体查询
多条记录的实体查询与单条记录相似,调用queryForList(String sql,QueryFormObject form,Class entity)方法,可以得到返回的实体类列表
其中的QueryFormObject 对象是框架中封装的查询参数对象,包含分页信息及查询条件.
QueryFormObject 的主要属性说明:
limit和start属性分别指定每页记录数和从第几条开始查询.
param属性是一个Object数组,用于传递查询参数
以上属性都有get和set方法可以使用
RowMappingTool也像EntityMappingTool一样提供setSeeRs方法使用
在spring中的配置
把以下内容加入到spring配置文件中,这是本框架的核心配置内容对应的class指定的包名称根据自己的实际情况修改
<!-- 读取配置文件 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- 数据库的相关配置 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">
<value>60</value>
</property>
</bean>
<!-- 为 JdbcTemplate 装配本地 JDBC 对象抽取器 -->
<bean id="nativeJdbcExtractor"
class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"
lazy-init="true"/>
<!-- 设置本地 Jdbc 对象抽取器 -->
<bean id="oracleLobHandler"
class="org.springframework.jdbc.support.lob.OracleLobHandler"
lazy-init="true">
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor"/>
</bean>
<!-- 设置 LOB 处理器 -->
<bean id="lobHelper" class="cn.jacore.db.LobHelper" scope="prototype">
<constructor-arg index="0" ref="oracleLobHandler"></constructor-arg>
</bean>
<!-- 公用数据库操作类 -->
<bean id="rowMappingTool" class="cn.jacore.tools.RowMappingTool" scope="prototype">
<property name="lobHandler" ref="oracleLobHandler"/>
</bean>
<bean id="entityMappingTool" class="cn.jacore.tools.EntityMappingTool" scope="prototype">
<property name="lobHandler" ref="oracleLobHandler"/>
</bean>
<bean id="jdbcBaseDb" class="cn.jacore.db.AbstractJdbcBaseDao">
<property name="lobHelper" ref="lobHelper"/>
<property name="rowMapping" ref="rowMappingTool"/>
<property name="entityMapping" ref="entityMappingTool"/>
</bean>
如果要在项目中定义一个自己的Dao,配置如下
<bean id="testDao" class="test.springmvc.TestDao" parent="jdbcBaseDb">
<property name="dataSource" ref="dataSource"/>
</bean>
我在AbstractJdbcBaseDao的setDataSource方法中把相关的数据库操作对象进行初始化,所以DAO只有指定了dataSource才能正常使用
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
jdbcTemplate = new JdbcTemplate(dataSource);
txJdbc = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
下面结出一个完整的程序代码
假设Dao已经完成了上面的配置
package test.springmvc;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import cn.jacore.db.AbstractJdbcBaseDao;
import cn.jacore.tools.PageObject;
import cn.jacore.tools.QueryFormObject;
public class TestDao extends AbstractJdbcBaseDao{
private Log log = LogFactory.getLog(this.getClass());
public PageObject queryList(QueryFormObject form){
PageObject page = new PageObject();
String sql = "select t.* from TEST_TESTTABLE t where 1=1";
if(form.getParam()!=null){
sql+=" and t.content like ?";
}
page.setList(super.queryForList(sql, form));
page.setCount(super.transToCount(sql, form));
return page;
}
}
在控制器中使用Dao,我这里使用的是spring的mvc,程序片段如下
package test.springmvc;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import cn.jacore.tools.PageObject;
import cn.jacore.tools.QueryFormObject;
@Controller
@RequestMapping(value="/test")
public class TestSpringController {
private Logger logger = Logger.getLogger(TestSpringController.class);
@Resource
private TestDao testDao;
@RequestMapping(value = "/testList.action")
@ResponseBody
public PageObject listUser(TestBean model,QueryFormObject form) {
logger.info("列表 "+" start : "+form.getStart()+" limit : "+form.getLimit()+" 条件 : "+model.getName());
if(!StringUtils.isEmpty(model.getName())){
form.setParam(new String[]{"%"+model.getName()+"%"});
}
PageObject page = testDao.queryList(form);
return page;
}
@RequestMapping(value = "/addTest.action")
@ResponseBody
public Map<String, Object> addTest(TestTable model) {
logger.info("捕获到前台传递过来的Model,内容为:" + model.getContent());
testDao.saveOrUpdate(model);
Map<String, Object> map = new HashMap<String, Object>(1);
map.put("success", "true");
map.put("model", model);
return map;
}
}
前台展示用了Extjs,表单用ajax提交
/*!
* Ext JS Library 3.1.1
* Copyright(c) 2006-2010 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
Ext.onReady(function() {
var form = Ext.create('Ext.form.Panel',{
baseCls: 'x-plain',
layout:'absolute',
defaultType: 'textfield',
id : 'testForm',
items: [{
x: 0,
y: 35,
xtype:'label',
text: 'content:'
},{
x: 60,
y: 30,
name: 'content',
anchor: '100%' // anchor width by percentage
},{
x:0,
y: 60,
xtype: 'textarea',
id: 'resultMsg',
anchor: '100% 100%' // anchor width and height
}]
});
var window = new Ext.Window({
title: 'Resize Me',
width: 500,
height:300,
minWidth: 300,
minHeight: 200,
layout: 'fit',
plain:true,
bodyStyle:'padding:5px;',
buttonAlign:'center',
closeAction:'close',
items: form,
buttons: [{
text: 'Send',handler : function(){
var fp = Ext.getCmp('testForm');
fp.getForm().submit({
url: ROOTURL+'/test/addTest.action',
waitTitle:'正在保存',
waitMsg: '请稍等',
success: function(form, action){
Ext.MessageBox.show({
title: '提示ʾ',
msg: '保存成功 ',
buttons: Ext.MessageBox.OK,
icon: Ext.MessageBox.INFO
});
Ext.getCmp('resultMsg').setRawValue('id : '+action.result.model.nid);
},
failure:function(form,action){
Ext.MessageBox.show({
title: '提示',
msg: '保存失败',
buttons: Ext.MessageBox.OK,
icon: Ext.MessageBox.ERROR
});
}
});
}
},{
text: 'Cancel',handler : function(){
var fp = Ext.getCmp('testForm');
fp.load({
url: ROOTURL+'/test/testLoad.action',
success: function(form, action){},
failure:function(form,action){
Ext.MessageBox.show({
title: '提示',
msg: '保存失败',
buttons: Ext.MessageBox.OK,
icon: Ext.MessageBox.ERROR
});
}
});
}
}]
});
window.show();
});
优快云不让自己删除重新传,我放迅雷快传里了
实例程序打包下载