1. JdbcTemplate介紹
它是 spring 框架中提供的一個對象,是對原始 Jdbc API 對象的簡單封裝。
2. 環境搭建
添加依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
3. 使用JdbcTemplate完成CRUD操作
首先要創建一個JdbcTemplate對象,構造方法有兩種選擇,空參構造和傳入DataSource構造。空參構造需要在創建對象後使用JdbcTemplate的setDataSource方法設置數據源後纔可以使用。
public JdbcTemplate() {
}
public JdbcTemplate(DataSource dataSource) {
this.setDataSource(dataSource);
this.afterPropertiesSet();
}
數據源可以選用spring自帶的org.springframework.jdbc.datasource.DriverManagerDataSource
(1)查詢所有用戶
public List query(String sql,@NotNull RowMapper rowMapper,Object…args)
實現方式一: 自己實現RowMapper接口,在mapRow方法中定義數據庫中的每一行數據封裝到實體類中的邏輯。
應用場景:實體類屬性名與數據庫字段名不相同。
public List<User> findAll() {
return jt.query("select * from user", new RowMapper<User>() {
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user = new User();
user.setId(resultSet.getInt("id"));
user.setSex(resultSet.getString("sex"));
user.setBirthday(resultSet.getDate("birthday"));
user.setUsername(resultSet.getString("username"));
return user;
}
});
}
實現方式二: 使用spring爲我們提供的實現類BeanPropertyRowMapper
應用場景:實體類屬性名與數據庫字段名相同
public List<User> findAll() {
return jt.query("select * from user", new BeanPropertyRowMapper<User>(User.class));
}
(2)查詢單個用戶
使用 查詢所有用戶 的實現方式二
public User findOne(Integer id) {
List<User> users=
jt.query("select * from user where id = ?",new BeanPropertyRowMapper<User>(User.class),id);
return users.isEmpty() ? null : users.get(0);
}
(3)保存,更新,刪除用戶
public int update(String sql,@Nullable Object… args)
public void saveUser(User user) {
jt.update("insert into user(username,sex,birthday) values(?,?,?)",
user.getUsername(),
user.getSex(),
user.getBirthday());
}
public void updateUser(User user) {
jt.update("update user set username = ?,sex = ?,birthday = ? where id = ?",
user.getUsername(),
user.getSex(),
user.getBirthday(),
user.getId());
}
public void deleteUser(Integer id) {
jt.update("delete from user where id = ?", id);
}
(4)查詢總記錄數
public T queryForObject(String sql,Class requiredType,@Nullable Object… args)
public int findTotal() {
return jt.queryForObject("select count(*) from user", Integer.class);
}
4. 使用spring的ioc完成對UserDao中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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置userDao-->
<bean id="userDao" class="cn.itcast.dao.impl.UserDaoImpl">
<property name="jt" ref="jdbcTemplate"></property>
</bean>
<!--配置JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" scope="prototype">
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
<!--配置數據源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/dbtest?serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
4. JdbcDaoSupport的使用
userDao中的JdbcTemplate對象是採用set方法注入的,所以需要寫setter方法。
如果有多個dao實現類,那麼類中都要定義一個JdbcTemplate對象以及編寫其setter方法。這種重複性的工作spring早已想到辦法幫我們解決了。只要每個dao實現類都繼承JdbcDaoSupport,然後再爲每個dao實現類注入一個數據源,就可以直接獲取JdbcTemplate對象並使用了。
public class UserDaoImpl extends JdbcDaoSupport implements UserDao {
public List<User> findAll() {
return super.getJdbcTemplate().query("select * from user",
new BeanPropertyRowMapper<User>(User.class));
}
}
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置userDao-->
<bean id="userDao" class="cn.itcast.dao.impl.UserDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置數據源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/dbtest?serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
JdbcDaoSupport是如何實現簡化我們書寫的?
public abstract class JdbcDaoSupport extends DaoSupport {
@Nullable
private JdbcTemplate jdbcTemplate;
public final void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
this.jdbcTemplate = this.createJdbcTemplate(dataSource);
this.initTemplateConfig();
}
}
protected JdbcTemplate createJdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Nullable
public final JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}
}
可以看到只要爲JdbcDaoSupport注入一個數據源,它就會判斷當前對象是否有jdbcTemplate對象或者數據源是否更換,如果沒有jdbcTemplate對象或者數據源更換,它就會創建一個新的jdbcTemplate對象。那麼dao實現類繼承它,自然可以使用getJdbcTemplate方法來獲取jdbcTemplate對象並使用。
5. 什麼時候選擇JdbcDaoSupport?
基於註解的配置的時候,會使用@Repository註解把dao實現類對象加入到IOC容器中,這樣我們就無法通過配置xml的方式爲dao實現類對象注入數據源了。沒有數據源就無法使用jdbcTemplate對象,此時繼承JdbcDaoSupport就沒意義了。
總結: spring基於註解開發時不要繼承JdbcDaoSupport,基於xml開發時可以讓dao實現類繼承JdbcDaoSupport來簡化我們的開發。
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Autowired
private jdbcTemplate jt;
public List<User> findAll() {
return jt.query("select * from user",
new BeanPropertyRowMapper<User>(User.class));
}
}