Spring——JdbcTemplate封装Jdbc

1. Spring 中使用 JdbcTemplate 封装对 Jdbc 的支持,使用 Spring JdbcTeamplate 的例子如下:

(1). 假设如下 SQL 表中有数据 username=test1,passwd=test1,address=test1

 

 

(2).Spring 配置文件中添加关于数据源和 JdbcTeamplate 的配置如下:

 

 

(3).Java 持久化对象如下:

 

 

(4). 使用 JdbcTeamplateDAO 如下:

 

 

2.Spring JdbcTemplate 的工作流程:

通过 1 中的小例子,我们可以总结出 Spring JdbcTemplate 的工作流程如下:

(1). 配置数据源:

Spring 中,将管理数据库连接的数据源当作普通 Java Bean 一样在 Spring IoC 容器中管理,当应用使用数据源时 Spring IoC 容器负责初始化数据源。

(2). 将数据源注入 JdbcTemplate

JdbcTemplatedataSource 属性用于注入配置的数据源, Spring IoC 容器通过依赖注入将配置的数据源注入到 SpringJdbc 操作的封装类 JdbcTemplate 中。

(3). 应用中使用 JdbcTemplate

注入了数据源的 JdbcTemplate 就可以在应用中使用了,应用中对数据源的增删改查等操作都可以使用 JdbcTemplate 对外提供的方法操作数据库。

3. JdbcTemplate 处理 Statement 的相关方法实现:

JdbcTemplateexecute 方法是 JdbcTemplate 的核心方法,是 JdbcTemplate 调用 jdbc 进行查询,添加,删除和更新操作的基础方法,在 execute 方法中,主要实现对数据库的基本操作,如:获取数据库连接;根据应用对数据库的需要创建数据库的 Statement ;对数据库操作进行回调;处理数据库异常;关闭数据库连接等等。 JdbcTemplate 中有真的 JdbcStatement PreparedStatement CallableStatement 处理的 execute 方法 ,首先我们分析 处理 Statement 的相关方法:

(1). 处理 Statementexecute 方法:

 

 

Execute 方法是 JdbcTemplate 执行 jdbc 操作的核心,其他的方法都是通过调用 execute 方法来操作数据库。

 

(2). Statement 的查询方法:

JdbcTemplate 处理 Statement 的查询方法有很多,但是其中最基本的方法源码如下:

 

 

(3).Statement 的更新方法:

 

 

通过对 Statement 相关处理的方法源码分析,我们可以看出 execute 方法是核心方法,在 execute 方法中,主要获取数据库连接和创建 Statement ,同时当执行完 jdbc 操作之后释放连接和资源等数据库操作的通用流程,所有的查询,更新等具体操作均是通过向 execute 方法传递合适的回调参数来使用 execute 方法中的数据库通用流程和资源,真正执行 jdbc 操作的方法由具体的回调内部类来实现。

4. JdbcTemplate 处理 PreparedStatement 的相关方法实现:

 

(1). 处理 PreparedStatement execute 方法:

 

 

 

(2). PreparedStatement 的查询方法:

Statement 类似, JdbcTemplatePreparedStatement 的查询方法也非常多,我们以最基本的查询方法源码为例分析其处理流程:

 

 

(3). PreparedStatement 的更新方法:

 

 

通过对 PreparedStatement 相关处理方法的源码分析,我们可以看到 PreparedStatement Statement 的处理流程基本是相同的,不同之处在于 PreparedStatement 需要处理设置参数值的操作。

 

5. JdbcTemplate 处理 CallableStatement 的相关方法实现:

(1). 处理 CallableStatementexecute 方法:

 

 

(2). CallableStatement call 方法:

 

 

通过上面对 CallableStatement 相关处理方法的源码分析我们可以看到, execute 方法基本和 StatementPreparedStatement 是相同的,不同之处在于 CallableStatement 是通过 jdbc 调用数据库的存储过程,对于输入输出参数的组装,以及返回结果的处理方面有些特殊处理。

 

6. JdbcTemplate 通过 DataSourceUtils 获取数据库连接:

JdbcTemplateexecute 方法中通过 DataSourceUtils .getConnection(getDataSource()); 获取数据库连接,下面我们就分析 DataSourceUtils 类获取数据库连接的实现过程:

 

 

 

通过对 JdbcTemplate的源码分析,我们看到Spring只是将jdbc的一些常用操作封装,将通用的获取数据库连接、创建创建Statement、关闭资源释放连接等操作封装在不同种类的execute方法中,同时调用不同的回调处理Action来具体执行jdbc操作,对jdbc熟悉的人很容易看懂这部分源码,当然Spring还对jdbc进行了一些高级的封装和扩展,例如RowMapper将结果集转换为指定对象等,这部分有兴趣可以自己研究。

//获取数据库连接的入口方法 public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { try { //通过doGetConnection方法来获取数据库连接 return doGetConnection(dataSource); } catch (SQLException ex) { throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex); } } //获取数据库连接 public static Connection doGetConnection(DataSource dataSource) throws SQLException { Assert.notNull(dataSource, "No DataSource specified"); //把数据库连接放到事务管理器中管理 //通过TransactionSynchronizationManager中定义的线程局部 //变量(threadlocal)来和线程绑定数据库连接 ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); //如果TransactionSynchronizationManager中已有与当前线程绑定的数据库连接 if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) { //从当前线程线程局部变量中获取数据库连接 conHolder.requested(); //如果当前线程局部变量中没有绑定数据库连接,则为当前线程局部变量设置数据库连接 if (!conHolder.hasConnection()) { logger.debug("Fetching resumed JDBC Connection from DataSource"); conHolder.setConnection(dataSource.getConnection()); } //直接返回TransactionSynchronizationManager线程局部变量中的数据库连接 return conHolder.getConnection(); } //如果TransactionSynchronizationManager中没有和当前线程绑定的数据 //库连接,则从Spring配置文件配置的数据源对象中获取数据库连接 logger.debug("Fetching JDBC Connection from DataSource"); Connection con = dataSource.getConnection(); //如果当前线程事务同步是Active的,即在注册之前可以直接使用,避免不必要 //的实例对象创建 if (TransactionSynchronizationManager.isSynchronizationActive()) { logger.debug("Registering transaction synchronization for JDBC Connection"); //在事务中使用同一个数据库连接做jdbc操作,当事务结束后,线程绑定对象 //将被同步移除 ConnectionHolder holderToUse = conHolder; //如果存放数据库连接的线程局部变量为null,则重新创建一个线程局部变量 if (holderToUse == null) { holderToUse = new ConnectionHolder(con); } //如果存放数据库连接的线程局部变量不为null,则将数据库连接存放到线程 //局部变量中 else { holderToUse.setConnection(con); } //请求数据库连接 holderToUse.requested(); //为当前线程注册事务同步 TransactionSynchronizationManager.registerSynchronization( new ConnectionSynchronization(holderToUse, dataSource)); //标记当前数据库连接为事务同步 holderToUse.setSynchronizedWithTransaction(true); if (holderToUse != conHolder) { //将数据源绑定到当前线程局部变量 TransactionSynchronizationManager.bindResource(dataSource, holderToUse); } } return con; }

//CallableStatement调用数据库的存储过程 public Map<String, Object> call(CallableStatementCreator csc, List<SqlParameter> declaredParameters) throws DataAccessException { final List<SqlParameter> updateCountParameters = new ArrayList<SqlParameter>(); final List<SqlParameter> resultSetParameters = new ArrayList<SqlParameter>(); final List<SqlParameter> callParameters = new ArrayList<SqlParameter>(); //遍历声明的参数 for (SqlParameter parameter : declaredParameters) { //如果参数是结果参数 if (parameter.isResultsParameter()) { //如果参数是返回结果集类型,则将参数添加到结果集参数集合中 if (parameter instanceof SqlReturnResultSet) { resultSetParameters.add(parameter); } //如果参数不是返回结果集类型,则将参数添加到更新数目参数集合中 else { updateCountParameters.add(parameter); } } //如果参数不是结果参数,则将参数添加到调用参数集合中 else { callParameters.add(parameter); } } //调用CallableStatement的execute方法,第二个参数是实现了//CallableStatementCallback接口的匿名内部类,用于回调 return execute(csc, new CallableStatementCallback<Map<String, Object>>() { //真正调用jdbc操作的方法 public Map<String, Object> doInCallableStatement(CallableStatement cs) throws SQLException { //CallableStatement执行jdbc调用,如果是返回结果为结果集则为//ture,如果执行返回结果不是结果集则返回false boolean retVal = cs.execute(); //获取CallableStatement执行后数据库中被更新的记录数 int updateCount = cs.getUpdateCount(); if (logger.isDebugEnabled()) { logger.debug("CallableStatement.execute() returned '" + retVal + "'"); logger.debug("CallableStatement.getUpdateCount() returned " + updateCount); } //创建一个用于返回指向结果的集合 Map<String, Object> returnedResults = createResultsMap(); //如果CallableStatement执行的返回结果结果是结果集,或者 //CallableStatement执行的更新操作,数据库中有记录被更新 if (retVal || updateCount != -1) { //将存储过程调用结果提取成结果集集合 returnedResults.putAll(extractReturnedResults(cs, updateCountParameters, resultSetParameters, updateCount)); } //如果CallableStatement执行的返回结果不是结果集,且不是更新操作, //则将存储过程的输出参数提取为结果集 returnedResults.putAll(extractOutputParameters(cs, callParameters)); return returnedResults; } }); }

 

//CallableStatement处理给定字符串的 public <T> T execute(String callString, CallableStatementCallback<T> action) throws DataAccessException { //将字符串封装为SimpleCallableStatementCreator类,调用execute方法处//理CallableStatement return execute(new SimpleCallableStatementCreator(callString), action); } //CallableStatement的execute方法,第一个参数CallableStatementCreator是封装调用字//符串的类,封装调用数据库存储过程的语句 public <T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action) throws DataAccessException { Assert.notNull(csc, "CallableStatementCreator must not be null"); Assert.notNull(action, "Callback object must not be null"); if (logger.isDebugEnabled()) { String sql = getSql(csc); logger.debug("Calling stored procedure" + (sql != null ? " [" + sql + "]" : "")); } //根据数据源获取数据库连接 Connection con = DataSourceUtils.getConnection(getDataSource()); CallableStatement cs = null; try { Connection conToUse = con; //如果JdbcTemplate指定了本地jdbc提取器,则将获取到的数据库连接转换为 //本地数据库连接 if (this.nativeJdbcExtractor != null) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); } //根据数据库连接创建CallableStatement cs = csc.createCallableStatement(conToUse); applyStatementSettings(cs); CallableStatement csToUse = cs; //如果JdbcTemplate指定了本地jdbc提取器,则将CallableStatement转换为 //本地CallableStatement if (this.nativeJdbcExtractor != null) { csToUse = this.nativeJdbcExtractor.getNativeCallableStatement(cs); } //调用相应回调对象的方法,执行jdbc操作 T result = action.doInCallableStatement(csToUse); handleWarnings(cs); return result; } catch (SQLException ex) { //清除CallableStatement参数 if (csc instanceof ParameterDisposer) { ((ParameterDisposer) csc).cleanupParameters(); } String sql = getSql(csc); csc = null; //关闭CallableStatement JdbcUtils.closeStatement(cs); cs = null; //释放数据库连接 DataSourceUtils.releaseConnection(con, getDataSource()); con = null; //将jdbc异常封装为Spring异常 throw getExceptionTranslator().translate("CallableStatementCallback", sql, ex); } finally { //清除CallableStatement参数 if (csc instanceof ParameterDisposer) { ((ParameterDisposer) csc).cleanupParameters(); } //关闭CallableStatement JdbcUtils.closeStatement(cs); //释放数据库连接 DataSourceUtils.releaseConnection(con, getDataSource()); } }

// PreparedStatement更新方法,第二个参数PreparedStatementSetter为向//PreparedStatement设置参数的类 protected int update(final PreparedStatementCreator psc, final PreparedStatementSetter pss) throws DataAccessException { logger.debug("Executing prepared SQL update"); //调用PreparedStatement的execute方法,第二个参数为实现了//PreparedStatementCallback接口的匿名内部类,由PreparedStatement的 //execute方法回调 return execute(psc, new PreparedStatementCallback<Integer>() { //真正执行jdbc操作的方法 public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException { try { //为PreparedStatement设置参数值 if (pss != null) { pss.setValues(ps); } //PreparedStatement调用jdbc的更新操作,返回受影响的行数 int rows = ps.executeUpdate(); if (logger.isDebugEnabled()) { logger.debug("SQL update affected " + rows + " rows"); } return rows; } finally { //清除PreparedStatement参数 if (pss instanceof ParameterDisposer) { ((ParameterDisposer) pss).cleanupParameters(); } } } }); }

//PreparedStatement查询方法,第一个参数PreparedStatementCreator为封装sql语句的//类,第二个参数PreparedStatementSetter为向PreparedStatement设置参数的类,第三//个参数ResultSetExtractor为处理结果集的类 public <T> T query( PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse) throws DataAccessException { Assert.notNull(rse, "ResultSetExtractor must not be null"); logger.debug("Executing prepared SQL query"); //调用PreparedStatement的execute方法,第二个参数为一个实现了//PreparedStatementCallback接口的匿名内部类,被execute回调 return execute(psc, new PreparedStatementCallback<T>() { //执行jdbc操作的方法 public T doInPreparedStatement(PreparedStatement ps) throws SQLException { ResultSet rs = null; try { //如果PreparedStatement参数不为null,则为PreparedStatement设置参数值 if (pss != null) { pss.setValues(ps); } //执行jdbc查询操作 rs = ps.executeQuery(); ResultSet rsToUse = rs; //如果JdbcTemplate指定了本地jdbc提取器,则将查询得到的结果 //集转换为本地jdbc结果集 if (nativeJdbcExtractor != null) { rsToUse = nativeJdbcExtractor.getNativeResultSet(rs); } //使用配置的结果集处理器提取结果集数据 return rse.extractData(rsToUse); } finally { //关闭结果集 JdbcUtils.closeResultSet(rs); //清除PreparedStatement参数 if (pss instanceof ParameterDisposer) { ((ParameterDisposer) pss).cleanupParameters(); } } } }); }

 

//PreparedStatement处理sql语句的execute方法 public <T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException { //将sql语句封装成为SimplePreparedStatementCreator,调用处理//PreparedStatement的方法 return execute(new SimplePreparedStatementCreator(sql), action); } //处理PreparedStatement public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action) throws DataAccessException { Assert.notNull(psc, "PreparedStatementCreator must not be null"); Assert.notNull(action, "Callback object must not be null"); if (logger.isDebugEnabled()) { String sql = getSql(psc); logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : "")); } //获取数据库连接 Connection con = DataSourceUtils.getConnection(getDataSource()); PreparedStatement ps = null; try { Connection conToUse = con; //如果JdbcTemplate指定了jdbc本地提取器,则将获取到的数据库连接转换 //为本地数据库连接 if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); } //根据数据库连接和sql语句创建PreparedStatement ps = psc.createPreparedStatement(conToUse); applyStatementSettings(ps); PreparedStatement psToUse = ps; //如果JdbcTemplate指定了jdbc本地提取器,则将PreparedStatement转换 //为本地PreparedStatement if (this.nativeJdbcExtractor != null) { psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps); } //调用回调处理器,执行相应操作 T result = action.doInPreparedStatement(psToUse); handleWarnings(ps); return result; } catch (SQLException ex) { //关闭资源,释放连接 if (psc instanceof ParameterDisposer) { ((ParameterDisposer) psc).cleanupParameters(); } String sql = getSql(psc); psc = null; JdbcUtils.closeStatement(ps); ps = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; //将jdbc相关异常封装转换为Spring异常向调用者抛出 throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex); } finally { //清除PreparedStatement的参数 if (psc instanceof ParameterDisposer) { ((ParameterDisposer) psc).cleanupParameters(); } //关闭PreparedStatement JdbcUtils.closeStatement(ps); //释放数据库连接 DataSourceUtils.releaseConnection(con, getDataSource()); } }

//静态sql的更新方法 public int update(final String sql) throws DataAccessException { Assert.notNull(sql, "SQL must not be null"); if (logger.isDebugEnabled()) { logger.debug("Executing SQL update [" + sql + "]"); } //实现了StatementCallback和SqlProvider接口的内部类,Statement //的execute方法回调 class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider { //Statement的execute方法更新操作时回调方法,真正执行jdbc操作的方法 public Integer doInStatement(Statement stmt) throws SQLException { //Statement执行jdbc的更新操作,返回影响行数 int rows = stmt.executeUpdate(sql); if (logger.isDebugEnabled()) { logger.debug("SQL update affected " + rows + " rows"); } return rows; } public String getSql() { return sql; } } //调用Statement的execute方法 return execute(new UpdateStatementCallback()); }

//静态sql的查询方法,第二个参数ResultSetExtractor是查询结果集转换器,用于处理查//询得到的结果集 public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException { Assert.notNull(sql, "SQL must not be null"); Assert.notNull(rse, "ResultSetExtractor must not be null"); if (logger.isDebugEnabled()) { logger.debug("Executing SQL query [" + sql + "]"); } //实现了StatementCallback和SqlProvider接口的内部类,用于execute方法回调 class QueryStatementCallback implements StatementCallback<T>, SqlProvider { //execute方法执行查询操作时回调方法,真正执行jdbc操作的方法 public T doInStatement(Statement stmt) throws SQLException { ResultSet rs = null; try { //调用Statement的查询方法 rs = stmt.executeQuery(sql); ResultSet rsToUse = rs; //如果JdbcTemplate指定了本地jdbc提取器,则将查询得到的结果 //集提取为本地结果集 if (nativeJdbcExtractor != null) { rsToUse = nativeJdbcExtractor.getNativeResultSet(rs); } //使用结果集提取器对查询得到的结果集进行处理 return rse.extractData(rsToUse); } finally { //关闭结果集 JdbcUtils.closeResultSet(rs); } } //获取sql public String getSql() { return sql; } } //调用处理Statement的execute方法 return execute(new QueryStatementCallback()); }

//execute方法执行的是输入的sql语句,且没有返回值的 public void execute(final String sql) throws DataAccessException { if (logger.isDebugEnabled()) { logger.debug("Executing SQL statement [" + sql + "]"); } //内部类,实现类StatementCallback和SqlProvider接口,执行sql语句的回调类 class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider { //JdbcTemplate中真正执行输入的sql语句的地方 public Object doInStatement(Statement stmt) throws SQLException { stmt.execute(sql); return null; } //获取输入的sql语句 public String getSql() { return sql; } } //调用通用的处理静态sql语句的execute方法 execute(new ExecuteStatementCallback()); } //通用的处理静态sql语句 public <T> T execute(StatementCallback<T> action) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); //根据配置的数据源获取数据库连接 Connection con = DataSourceUtils.getConnection(getDataSource()); Statement stmt = null; try { Connection conToUse = con; //如果JdbcTemplate指定了本地连接,则将获取到的数据库连接转换为本地连接 if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); } //创建Statement stmt = conToUse.createStatement(); applyStatementSettings(stmt); Statement stmtToUse = stmt; //如果JdbcTemplate指定了本地连接,则将Statement转换为本地Statement if (this.nativeJdbcExtractor != null) { stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt); } //调用ExecuteStatementCallback类的doInStatement回调方法,执行sql语句 T result = action.doInStatement(stmtToUse); handleWarnings(stmt); //返回执行结果 return result; } catch (SQLException ex) { //产生异常,则关闭Statement JdbcUtils.closeStatement(stmt); stmt = null; //释放数据库连接 DataSourceUtils.releaseConnection(con, getDataSource()); con = null; //将数据库异常封装为Spring异常向调用者抛出 throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex); } finally { //关闭Statement,释放数据库连接 JdbcUtils.closeStatement(stmt); DataSourceUtils.releaseConnection(con, getDataSource()); } }

package SpringJDBCSupport.ReadData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.List; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowCallbackHandler; public class PersonDAO { private JdbcTemplate jdbcTemplate; public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public int insertPersonUseUpdate(Person person){ String sql="insert into login values(?,?,?)"; Object[] params=new Object[]{ person.getName(), person.getPassword(), person.getAddress() }; return this.getJdbcTemplate().update(sql,params); } public int insertPersonUseExecute(Person person){ String sql="insert into login values(?,?,?)"; Object[] params=new Object[]{ person.getName(), person.getPassword(), person.getAddress() }; int[] types=new int[]{ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR }; return this.getJdbcTemplate().update(sql,params,types); } public int[] updatePersonUseBatchUpdate( final List persons){ String sql="insert into login values(?,?,?)"; BatchPreparedStatementSetter setter=null; //使用匿名内部类,实现BatchPreparedStatementSetter接口,实现批量更新 setter=new BatchPreparedStatementSetter(){ public int getBatchSize(){ return persons.size(); } public void setValues(PreparedStatement ps,int index) throws SQLException{ Person person=(Person)persons.get(index); ps.setString(1,person.getName()); ps.setString(2,person.getPassword()); ps.setString(3,person.getAddress()); } }; return this.getJdbcTemplate().batchUpdate(sql,setter); } public Person getPersonByRowCallbackHandler(String username){ String sql="select * from login where username=?"; final Person person=new Person(); final Object params[]=new Object[]{username}; //使用匿名内部类,实现RowCallbackHandler接口,即实现查询结果集的RowMapping this.getJdbcTemplate().query(sql,params,new RowCallbackHandler(){ public void processRow(ResultSet rs)throws SQLException{ person.setName(rs.getString("username")); person.setPassword(rs.getString("passwd")); person.setAddress(rs.getString("address")); } }); return person; } }

package SpringJDBCSupport.ReadData; import com.mysql.jdbc.Driver; public class Person { private String name; private String password; private String address; public Person(){ } public Person(String name,String password,String address){ this.name=name; this.password=password; this.address=address; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String toString(){ return this.getName()+"-"+this.getPassword()+"-"+this.getAddress(); } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" > <beans> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/javaee</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>1234</value> </property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref local="dataSource"/> </property> </bean> <bean id="personDAO" class="SpringJDBCSupport.ReadData.PersonDAO"> <property name="jdbcTemplate"> <ref local="jdbcTemplate"/> </property> </bean> </beans>
CREATE TABLE `login` ( `username` varchar(10) default NULL, `passwd` varchar(10) default NULL, `address` varchar(10) default NULL ) ENGINE=InnoDB DEFAULT CHARSET=gb2312;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值