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”,则可以顺利执行。