最近看了看spring的东西,发现注解是个好东西。不过在应用到JDBC DAO的时候遇到点小麻烦。现在和大家分享一下。
我们知道我们使用spring的JDBC功能时候,无非是继承spring提供的三个JDBC DAO的父类。
JdbcDaoSupport,NamedParameterJdbcDaoSupport,SimpleJdbcDaoSupport。其中在3.0以后SimpleJdbcDaoSupport已经被标记为过期了。原因是3.0以后只支持JAVA5环境应用,所以SimpleJdbcDaoSupport的特性前两个DAO父类都已经提供了。
在原来上我们继承这个种DAO的父类目的主要是为了使用它们自己JDBC模板。
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.core.namedparam;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
* Extension of JdbcDaoSupport that exposes a NamedParameterJdbcTemplate as well.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @since 2.0
* @see NamedParameterJdbcTemplate
*/
public class NamedParameterJdbcDaoSupport extends JdbcDaoSupport {
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
/**
* Create a NamedParameterJdbcTemplate based on the configured JdbcTemplate.
*/
@Override
protected void initTemplateConfig() {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate());
}
/**
* Return a NamedParameterJdbcTemplate wrapping the configured JdbcTemplate.
*/
public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
return namedParameterJdbcTemplate;
}
}
上面是用NamedParameterJdbcDaoSupport类的源代码,我们发现其中有一个叫做NamedParameterJdbcTemplate的成员变量和一个getNamedParameterJdbcTemplatef方法。
我们在平时开发的时候就继承这个类,在自己的方法中调用getNamedParameterJdbcTemplate()方法获取模板。再利用模板的回调进行数据库操作,这就是Spring引以自豪的模板模式。有兴趣的可以查看模板模式这个比较牛X的设计模式,对大家的程序设计提高很有好处的。但是这种模式有一个比较大的问题,我估计伟大的ROD先生设计Spring这部分的时候没有想到后来JAVA世界中出现了注解这个东东,因为在spring早期版本的的时候还完全都是XML的配置时代。从源代码看这个类的设计是2003年的时候。在XML配置时代我们除了要继承spring的JDBC父类以外还有做一件事情很重要,就是在XML中配置Data source属性的注入。
<bean class="com.tjsinfo.springauto.dao.SubUserDAO"> <property name="dataSource" ref="dataSource"</property> </bean>
就想现在这样,可是现在是注解的天下了。大家都已少配置多注解多约定为时尚(不过我个人感觉过度的使用注解和约定对于软件管理的要求很重要)。我们怎么才能使datasouce注解的方式注入到自己的DAO内呢?
小弟我一开始想了很多办法都不行,比如自己定义一个datasouce成员变量,在变量上增加注解。后来我看看源代码突然领悟到。问题的关键不在于datasouce,其实我们只要可以获得JdbcTemplate就可以了。
我的实现如下
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <context:component-scan base-package="com.tjsinfo.springauto"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/springmvc" /> <property name="username" value="root" /> <property name="password" value="root" /> </bean> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <constructor-arg ref="dataSource" /> </bean> </beans>
在XML文件中配置一个NamedParameterJdbcTemplate,我用的是NamedParameterJdbcTemplate用别的模板的可以换成自己的熟悉的模板,对这个模板的注入DataSource。
自己的DAO中这样注解
package com.tjsinfo.springauto.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import com.tjsinfo.springauto.vo.User;
@Repository("userDAO")
public class SuperUserDAO implements IUserDAO {
@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private static final String ADDUSERSQL = "INSERT INTO `t_system_user` (`id`,`loginname`,`password`,`systemname`,`state`,`sort`) VALUES (:id,:loginname,:password,:systemname,:state,:sort);";
public Boolean addUser(User user) {
// TODO Auto-generated method stub
BeanPropertySqlParameterSource beanPropertySqlParameterSource = new BeanPropertySqlParameterSource(user);
namedParameterJdbcTemplate.update(ADDUSERSQL, beanPropertySqlParameterSource);
return true;
}
}
直接使用一个模板的成员变量,在上面注解而且连原来的spring的父类也不用继承了。也算是解耦了。
这是小弟的自己的解决办法,不知道会不会有什么问题,不过我自己JUnit测试操作都是可以的。
欢迎大家拍砖,spring博大精深献丑了。