最近看了看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博大精深献丑了。