第1章 Spring基礎:6、Spring的資料庫程式設計
學習目標:
Spring的資料庫程式設計:資料庫程式設計是網際網路程式設計的基礎,Spring框架為開發者提供了JDBC模板模式,即jdbcTemplate,它可以簡化許多程式碼,但在實際應用中jdbcTemplate並不常用。工作更多的時候,用的是Hibernate框架和MyBatis框架進行資料庫程式設計。學習大綱:
一、Spring JDBC的XML配置
二、Spring JDBC的Java配置
三、Spring JdbcTemplate的常用方法
四、基於@Transactional註解的宣告式事務管理
學習內容:
一、Spring JDBC的XML配置
本節Spring資料庫程式設計主要使用Spring JDBC模組的core和dataSource包。core包是JDBC的核心功能包,包括常用的JdbcTemplate類;dataSource包是訪問資料來源的工具類包。使用Spring JDBC操作資料庫,需要對其進行配置。
<!-- 配置資料來源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- MySQL資料庫驅動 -- >
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!-- 連線資料庫的URL -->
<property name="url" value="jdbc:mysql://localhost:3306/springtest?characterEncoding=utf8"/>
<!-- 連線資料庫的使用者名稱 -->
<property name= "username" value="root"/>
<!-- 連線資料庫的密碼 -->
<property name="password" value="root"/>
</bean>
<!-- 配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
配置JDBC模板時,需要將dataSource注入到jdbcTemplate,而在資料訪問層(如Dao類)使用jdbcTemplate時,也需要將jdbcTemplate注入到對應的Bean中。程式碼示例如下:
……
@Repository
public class TestDaoImpl implements TestDao{
@Autowired
//使用配置檔案中的JDBC模板
private JdbcTemplate jdbcTemplate;
……
}
二、Spring JDBC的Java配置
@Configuration //通過該註解來表明該類是一個Spring的配置,相當於一個xml檔案
@ComponentScan(basePackages = "dao") //配置掃描包
@PropertySource(value={"classpath:jdbc.properties"},ignoreResourceNotFound=true)
//配置多個屬性檔案時 value={"classpath:jdbc.properties","xx","xxx"}
public class SpringJDBCConfig {
@Value("${jdbc.url}")//注入屬性檔案jdbc.properties中的jdbc.url
private String jdbcUrl;
@Value("${jdbc.driverClassName}")
private String jdbcDriverClassName;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
/**
* 配置資料來源
*/
@Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource myDataSource = new DriverManagerDataSource();
// 資料庫驅動
myDataSource.setDriverClassName(jdbcDriverClassName);;
// 相應驅動的jdbcUrl
myDataSource.setUrl(jdbcUrl);
// 資料庫的使用者名稱
myDataSource.setUsername(jdbcUsername);
// 資料庫的密碼
myDataSource.setPassword(jdbcUsername);
return myDataSource;
}
/**
* 配置JdbcTemplate
*/
@Bean(value="jdbcTemplate")
public JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}
三、Spring JdbcTemplate的常用方法
獲取JDBC模板後,如何使用它是本節將要講述的內容。首先,需要了解JdbcTemplate類的常用方法。該類的常用方法是update()和query()方法。
public int update(String sql,Object args[])
該方法可以對資料表進行增加、修改、刪除等操作。使用args[]設定SQL語句中的引數,並返回更新的行數。示例程式碼如下:
String insertSql = "insert into user values(null,?,?)";
Object param1[] = {"chenheng1", "男"};
jdbcTemplate.update(sql, param1);
public List<T> query (String sql, RowMapper<T> rowMapper, Object args[])
該方法可以對資料表進行查詢操作。rowMapper將結果集對映到使用者自定義的類中(前提是自定義類中的屬性要與資料表的欄位對應)。示例程式碼如下:
String selectSql ="select * from user";
RowMapper<MyUser> rowMapper = new BeanPropertyRowMapper<MyUser>(MyUser.class);
List<MyUser> list = jdbcTemplate.query(sql, rowMapper, null);
下面通過一個例項【例1-8】演示Spring JDBC的使用過程
1.使用Eclipse建立Web應用並匯入JAR包
2.建立屬性檔案與配置類
在ch1_8應用的src目錄下,建立資料庫配置的屬性檔案jdbc.properties
在ch1_8應用的src目錄下,建立config包,並在該包中建立配置類SpringJDBCConfig。在該配置類中使用@PropertySource註解讀取屬性檔案jdbc.properties,並配置資料來源和JdbcTemplate
//jdbc.properties屬性檔案
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springtest?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
//SpringJDBCConfig
package config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration //通過該註解來表明該類是一個Spring的配置,相當於一個xml檔案
@ComponentScan(basePackages = {"dao","service"}) //配置掃描包
@PropertySource(value={"classpath:jdbc.properties"},ignoreResourceNotFound=true)
@EnableTransactionManagement//開啟宣告式事務的支援
//配置多個配置檔案 value={"classpath:jdbc.properties","xx","xxx"}
public class SpringJDBCConfig {
@Value("${jdbc.url}")//注入屬性檔案jdbc.properties中的jdbc.url
private String jdbcUrl;
@Value("${jdbc.driverClassName}")
private String jdbcDriverClassName;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
/**
* 配置資料來源
*/
@Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource myDataSource = new DriverManagerDataSource();
// 資料庫驅動
myDataSource.setDriverClassName(jdbcDriverClassName);
// 相應驅動的jdbcUrl
myDataSource.setUrl(jdbcUrl);
// 資料庫的使用者名稱
myDataSource.setUsername(jdbcUsername);
// 資料庫的密碼
myDataSource.setPassword(jdbcUsername);
return myDataSource;
}
/**
* 配置JdbcTemplate
*/
@Bean(value="jdbcTemplate")
public JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(dataSource());
}
/**
* 為資料來源新增事務管理器
*/
@Bean
public DataSourceTransactionManager transactionManager() {
DataSourceTransactionManager dt = new DataSourceTransactionManager();
dt.setDataSource(dataSource());
return dt;
}
}
3.建立資料表與實體類
使用Navicat for MySQL建立資料庫springtest
,並在該資料庫中建立資料表user,資料表user的結構如圖所示:
在ch1_8應用的src目錄下,建立包entity
,在該包中建立實體類MyUser
//MyUser
package entity;
public class MyUser
{
private Integer uid;
private String uname;
private String usex;
//省略set和get方法
public String toString() {
return "myUser[uid="+uid+",uname="+uname+",usex="+usex+"]";
}
}
4.建立資料訪問層
在ch1_8應用的src目錄下,建立包dao
,在該包中建立資料訪問介面TestDao
和介面實現類TestDaoImpl
。在實現類TestDaoImpl
中使用@Repository註解標註此類為資料訪問層,並使用@Autowired註解依賴注入JdbcTemplate。
//TestDao
package dao;
import java.util.List;
import entity.MyUser;
public interface TestDao {
public int update(String sql, Object[] param);
public List<MyUser> query(String sql, Object[] param);
}
//TestDaoImpl
package dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import entity.MyUser;
@Repository
public class TestDaoImpl implements TestDao{
@Autowired
//使用配置類中的JDBC模板
private JdbcTemplate jdbcTemplate;
/**
* 更新方法,包括新增、修改、刪除
* param為sql中的引數,如萬用字元?
*/
@Override
public int update(String sql, Object[] param) {
return jdbcTemplate.update(sql, param);
}
/**
* 查詢方法
* param為sql中的引數,如萬用字元?
*/
@Override
public List<MyUser> query(String sql, Object[] param) {
RowMapper<MyUser> rowMapper = new BeanPropertyRowMapper<MyUser>(MyUser.class);
return jdbcTemplate.query(sql, rowMapper);
}
}
5.建立業務邏輯層
在ch1_8應用的src
目錄下,建立包service
,在該包中建立資料訪問介面TestService
和介面實現類TestServiceImpl
。在實現類TestServiceImpl
中使用@Service註解標註此類為業務邏輯層,並使用@Autowired註解依賴注入TestDao。
//TestService
package service;
public interface TestService {
public void testJDBC();
}
//TestServiceImpl
package service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import dao.TestDao;
import entity.MyUser;
@Service
@Transactional
public class TestServiceImpl implements TestService{
@Autowired
public TestDao testDao;
@Override
public void testJDBC() {
String insertSql = "insert into user values(null,?,?)";
//陣列param的值與insertSql語句中?一一對應
Object param1[] = {"chenheng1", "男"};
Object param2[] = {"chenheng2", "女"};
Object param3[] = {"chenheng3", "男"};
Object param4[] = {"chenheng4", "女"};
String insertSql1 = "insert into user values(?,?,?)";
Object param5[] = {1,"chenheng5", "女"};
Object param6[] = {1,"chenheng6", "女"};
//新增使用者
testDao.update(insertSql, param1);
testDao.update(insertSql, param2);
testDao.update(insertSql, param3);
testDao.update(insertSql, param4);
//新增兩個ID相同的使用者,出現唯一性約束異常,使事物回滾。
testDao.update(insertSql1, param5);
testDao.update(insertSql1, param6);
//查詢使用者
String selectSql ="select * from user";
List<MyUser> list = testDao.query(selectSql, null);
for(MyUser mu : list) {
System.out.println(mu);
}
}
}
6.建立測試類
package config;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import service.TestService;
public class TestJDBC {
public static void main(String[] args) {
//初始化Spring容器ApplicationContext
AnnotationConfigApplicationContext appCon =
new AnnotationConfigApplicationContext(SpringJDBCConfig.class);
TestService ts = appCon.getBean(TestService.class);
ts.testJDBC();
appCon.close();
}
}
7.執行測試類
------》解決方案
Exception in thread "main" org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connect ion for transaction; nested exception is java.sql.SQLException: Access denied for user 'root'@'localhost' (using passwor d: YES)
未解決哭哭!
四、基於@Transactional註解的宣告式事務管理
@Transactional註解可以作用於介面、介面方法、類以及類方法上。當作用於類上時,該類的所有public方法將都具有該型別的事務屬性,同時,也可以在方法級別使用該註解來覆蓋類級別的定義。雖然@Transactional註解可以作用於介面、介面方法、類以及類方法上,但是Spring小組建議不要在介面或者介面方法上使用該註解,因為這隻有在使用基於介面的代理時它才會生效。
學習時間:
學習產出:
CSDN 技術部落格 1 篇