ref:https://www.yiibai.com/spring/spring-jdbctemplate-jdbcdaosupport-examples.html
1. 不使用JdbcTemplate示例:如果不用JdbcTemplate,必须创建大量的冗余代码(创建连接,关闭连接,处理异常)中的所有DAO数据库的操作方法 - 插入,更新和删除。它的效率并不是很高,容易出错和乏味。
conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, customer.getCustId());
2. 使用JdbcTemplate示例:使用JdbcTemplate可节省大量的冗余代码,因为JdbcTemplate类会自动处理它。
private DataSource dataSource;
private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
} public void insert(Customer customer){ String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)"; jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update(sql, new Object[] { customer.getCustId(),
customer.getName(),customer.getAge()
}); }
3. 使用JdbcDaoSupport示例通过扩展 JdbcDaoSupport,设置数据源,并且 JdbcTemplate 在你的类中不再是必需的,只需要正确的数据源注入JdbcCustomerDAO。可以使用 getJdbcTemplate()方法得到 JdbcTemplate。
customerDAO类函数:
public class JdbcCustomerDAO extends JdbcDaoSupport implements CustomerDAO
{
//no need to set datasource here
public void insert(Customer customer){
String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
customer.setName("test',2);show databases;#");//无法注入!spring自动将'进行转义。即使为test\',2)也无法注入。
getJdbcTemplate().update(sql, new Object[] { customer.getCustId(),customer.getName(),customer.getAge() }); }//此处将
4.相应的xml文件设置dataSource/customerDAO
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/yiibaijava" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean> </beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerDAO" class="com.yiibai.customer.dao.impl.JdbcCustomerDAO">
<property name="dataSource" ref="dataSource" />
</bean> </beans>
public String findCustomerNameById(int custId){
String sql = "SELECT NAME FROM CUSTOMER WHERE CUST_ID = ?";
String name = (String)getJdbcTemplate().queryForObject(
sql, new Object[] { custId }, String.class);
return name;
}//此处查询条件为int custID,显然php中整数型注入无法应用。
字符串查询情况:
public Customer findByCustomerName(String name){
String sql = "SELECT * FROM CUSTOMER WHERE NAME = ?";
name="name1';show databases;#";//spring直接转义'name1\';show databases;#'。无法注入!
Customer customer = (Customer)getJdbcTemplate().queryForObject(
sql, new Object[] { name }, new CustomerRowMapper());
return customer;
}
与php不同,java中对象为强类型,int无法注入,而字符串又直接转义,避免了注入的可能性。
public Customer findByCustomerId(int custId){ String sql = "SELECT * FROM CUSTOMER WHERE CUST_ID = ?"; Customer customer = (Customer)getJdbcTemplate().queryForObject(
sql, new Object[] { custId }, new CustomerRowMapper()); return customer;
} public class CustomerRowMapper implements RowMapper
{
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Customer customer = new Customer();
customer.setCustId(rs.getInt("CUST_ID"));
customer.setName(rs.getString("NAME"));
customer.setAge(rs.getInt("AGE"));
return customer;
}
}
为了解决这个问题,可以使用“命名参数”,SQL参数是由一个冒号开始后续定义的名称,而不是位置。在另外的,命名参数只是在SimpleJdbcTemplate类和NamedParameterJdbcTemplate支持。
例子向您展示如何使用命名参数在一个 INSERT 语句。
//insert with named parameter
public void insertNamedParameter(Customer customer){ String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (:custId, :name, :age)"; Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("custId", customer.getCustId());
parameters.put("name", customer.getName());
parameters.put("age", customer.getAge()); getSimpleJdbcTemplate().update(sql, parameters); }
示例 2 例子来说明如何使用命名参数在批处理操作语句。
public void insertBatchNamedParameter(final List<Customer> customers){ String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (:custId, :name, :age)"; List<SqlParameterSource> parameters = new ArrayList<SqlParameterSource>();
for (Customer cust : customers) {
parameters.add(new BeanPropertySqlParameterSource(cust));
} getSimpleJdbcTemplate().batchUpdate(sql,
parameters.toArray(new SqlParameterSource[0]));
}
8.spring web中xml配置jdbctemplate.
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/abc" />
<property name="resourceRef" value="true"/>
</bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean> <resource-ref>
<res-ref-name>
jdbc/abc
</res-ref-name>
<res-type>
javax.sql.DataSource
</res-type>
</resource-ref> tomcat/conf/context.xml:
<Resource name="jdbc/abc" auth="Container" type="javax.sql.DataSource"
...
</Resource >
9.getSimpleJdbcTemplate执行多行sql语句问题
在默认情况下,即datasource设置为"jdbc:mysql://192.168.0.10:3306/yiibai”,不能执行多行sql语句,将会产生错误:PreparedStatementCallback; bad SQL grammar。
若要执行多行语句,设置datasource为“jdbc:mysql://192.168.0.10:3306/yiibai?allowMultiQueries=true”,则可以顺利执行。