Spring Boot學習6:Spring Boot JDBC
資料來源是資料庫連線的來源,通過DataSource介面獲得
資料來源型別
1)通用型資料來源(javax.sql.DataSource)
主要使用場景:通用型資料庫,本地事務,一般通過Socket方式連線
2)分佈型資料來源(javax.sql.XADataSource)
主要使用場景:通用型資料庫,分散式事務,一般通過Socket方式連線
3)嵌入式資料來源(org.springframework.jdbc.datasource.embedded.EmbeddedDatabase)
主要使用場景:本地檔案系統資料庫,如HSQL,H2,Derby等
列舉:org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType
2 事務
事務用於提供資料完整性,並在併發訪問下確保資料檢視的一致性
例子:建立springboot專案,並引用包web,jdbc,mysql驅動
建立專案後,我們看一下幾個介面Driver,DriverManager,Connection,Statement,ResultSet
我們來建立資料庫連線
建立JdbcController
@RestController
public class Jdbc2Controller {
@Autowired
@Qualifier(value="dataSource")
private DataSource dataSource;
@RequestMapping("/user/getUsers")
public Map<String,Object> getUsers(@RequestParam(name="id",defaultValue = "1") String id){
Map<String,Object> data = new HashMap<String,Object>();
Connection connection=null;
Statement statement = null;
try {
connection = dataSource.getConnection();
statement = connection.createStatement();
String sql = "select * from user where id="+id;
// connection.prepareStatement()
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
int r_id = resultSet.getInt("id");
String r_name = resultSet.getString("name");
int r_age = resultSet.getInt("age");
data.put("id",r_id);
data.put("name",r_name);
data.put("age",r_age);
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
try{
connection.close();
statement.close();
}catch(SQLException e){
e.printStackTrace();
}
}
return data;
}
}
配置jdbc,在application.properties中配置:
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.jdbc.Driver
測試:
http://localhost:8080/user/getUsers?id=1
返回:
{"name":"xiaohuang","id":1,"age":1}
修改為防止sql注入的方式
@RestController
public class Jdbc2Controller {
@Autowired
@Qualifier(value="dataSource")
private DataSource dataSource;
@RequestMapping("/user/getUsers")
public Map<String,Object> getUsers(@RequestParam(name="id",defaultValue = "1") int id){
Map<String,Object> data = new HashMap<String,Object>();
Connection connection=null;
Statement statement = null;
try {
connection = dataSource.getConnection();
String sql = "select id,name,age from user where id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,id);
ResultSet resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
int r_id = resultSet.getInt("id");
String r_name = resultSet.getString("name");
int r_age = resultSet.getInt("age");
data.put("id",r_id);
data.put("name",r_name);
data.put("age",r_age);
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
try{
connection.close();
}catch(SQLException e){
e.printStackTrace();
}
}
return data;
}
}
3.JDBC4.0
例子:使用事務操作
package com.segmentfault.springbootlesson7; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCallback; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import pojo.User; import java.sql.PreparedStatement; import java.sql.SQLException; @Service @EnableTransactionManagement public class UserServiceImpl implements UserService { @Autowired private JdbcTemplate jdbcTemplate; @Override @Transactional(propagation = Propagation.REQUIRED,isolation= Isolation.SERIALIZABLE) public String save(User user) { Object obj = jdbcTemplate.execute("insert into user (name,age) values(?,?)", new PreparedStatementCallback<Object>() { @Override public Boolean doInPreparedStatement(PreparedStatement preparedStatement) throws SQLException, DataAccessException { preparedStatement.setString(1,"zhejaing"); preparedStatement.setInt(2,100); return preparedStatement.executeUpdate()>0; } }); return obj.toString(); } }
例子:使用jdbc獲取到資料庫中的後設資料以及資料
@Autowired @Qualifier(value="dataSource") private DataSource dataSource; @Autowired private JdbcTemplate jdbcTemplate;
@RequestMapping("/user") public List<Map<String,Object>> getUser(){ List<Map<String,Object>> data = jdbcTemplate.execute("select * from user", new PreparedStatementCallback<List<Map<String,Object>>>() { @Override public List<Map<String, Object>> doInPreparedStatement(PreparedStatement preparedStatement) throws SQLException, DataAccessException { ResultSet resultSet = preparedStatement.executeQuery(); ResultSetMetaData metaData = resultSet.getMetaData(); int columnCount = metaData.getColumnCount(); List<String> columnNameList = new ArrayList<String>(columnCount); for(int i=1;i<=columnCount;i++){ String columnName = metaData.getColumnName(i); columnNameList.add(columnName); } List<Map<String,Object>> data = new LinkedList<>(); while(resultSet.next()){ Map<String,Object> columnData = new LinkedHashMap<>(); for(String columnName:columnNameList){ Object columnValue = resultSet.getObject(columnName); columnData.put(columnName,columnValue); data.add(columnData); } } return data; } }); return data; }
執行測試
[{"id":1,"name":"xiaohuang","age":1},{"id":1,"name":"xiaohuang","age":1},{"id":1,"name":"xiaohuang","age":1},{"id":2,"name":"xiaolong","age":22},{"id":2,"name":"xiaolong","age":22},{"id":2,"name":"xiaolong","age":22},{"id":3,"name":"xiaolong","age":23},{"id":3,"name":"xiaolong","age":23},{"id":3,"name":"xiaolong","age":23},{"id":4,"name":"John","age":18},{"id":4,"name":"John","age":18},{"id":4,"name":"John","age":18}]
還需要注意Transactional的底層原始碼,可以自行再次除錯學習
使用Transactional,會自動封裝物件,並強化事務功能
啟動代理有兩種,
介面的程式碼,是jdk的預設代理proxy,
@Autowired private UserService userService;
@Service @EnableTransactionManagement(proxyTargetClass = false) public class UserServiceImpl implements UserService {
對類進行代理,那麼需要使用到cglib
@Autowired private UserServiceImpl userService;
@Service @EnableTransactionManagement(proxyTargetClass = true) public class UserServiceImpl implements UserService {
4.微服務的分散式事務
使用Bitronix,
在start.spring.io上建立專案,並引用相關包
我們可以瞭解一下JTA相關的知識
http://blog.csdn.net/habren/article/details/52090773
https://www.ibm.com/developerworks/cn/java/j-lo-jta/
兩階段提交原理
tomcat中,分散式事務需要使用原始方法,UserTransaction, UserTransactionManager
5.問題
tomcat下面跨多個資料庫的分散式事務有什麼好的方法和建議?
UserTransaction,UserTransactionManager等了解下
如何高效學習JSR規範,有哪些規範值得關注?
Web:Servlet,WebSocket,WebService等
最重要的是Java JDBC規範,Java虛擬機器規範等
JSR規範主要:
DI
JaxB
JDBC
JMX(事務,點對點,高階協議)
JPA
JSTL
JSP
JTA
LANG
REST
SAX
SOAP
WEBSERVICE
WEBSOCKET
XML
WSDL
等
3)問題,Spring事務的底層實現,遇到RuntimeException才會回滾,為什麼?
因為SpringBoot裡面基本上都是執行時異常,但是Transactional註解可以指定哪些異常可以被回滾,哪些異常不回滾等
4)springboot動態切換資料來源的解決方案?
5)jdbc的connection和Orm比如Hibernate中的session什麼關係?如果將Hibernate的一級快取關了?
connection無狀態,session有狀態。
Hibernate的一級環境可以通過程式碼的方式關閉,不可通過配置方式關閉。
6)手動事務
PlatformTransactionManager事務管理器
TransactionStatus事務狀態
例子:
@Autowired private PlatformTransactionManager platformTransactionManager;
public Boolean save2(User usr){ DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition); Boolean result = null; try { result = save(usr); platformTransactionManager.commit(transactionStatus); } catch (Exception e) { e.printStackTrace(); platformTransactionManager.rollback(transactionStatus); } return result; }
相關文章
- Spring Boot 學習筆記(2):JDBCSpring Boot筆記JDBC
- Spring Boot學習(一)——Spring Boot介紹Spring Boot
- Spring boot學習(三) Spring boot整合mybatisSpring BootMyBatis
- spring boot學習Spring Boot
- Spring Boot 學習Spring Boot
- Spring Boot學習3:web篇(中)-Spring boot Rest學習Spring BootWebREST
- Spring boot學習(二) Spring boot基礎配置Spring Boot
- Spring boot學習(四)Spring boot整合DruidSpring BootUI
- Spring boot學習(一)開啟Spring boot之旅Spring Boot
- Spring Boot學習筆記:Spring Boot核心配置Spring Boot筆記
- Spring Boot學習5:spring-boot web容器Spring BootWeb
- Spring Boot學習4:web篇(下)-Spring boot (Servlet,Jsp)學習Spring BootWebServletJS
- Spring boot學習(九)Spring boot配置郵件傳送Spring Boot
- Spring boot學習(八)Spring boot配置ehcache快取框架Spring Boot快取框架
- Spring boot學習(五)Spring boot整合Mybatis Generator以及PageHelperSpring BootMyBatis
- Spring Boot學習之---Spring Boot與檢索 下(十六)Spring Boot
- Spring Boot 學習目錄Spring Boot
- Spring Boot 學習-基礎Spring Boot
- 什麼是Spring Boot?為什麼要學習Spring Boot?Spring Boot
- Spring Boot + JPA學習總結Spring Boot
- Spring boot學習(六)Spring boot實現AOP記錄操作日誌Spring Boot
- Spring Boot:Spring Boot配置MybatisSpring BootMyBatis
- 重學 Spring BootSpring Boot
- spring-boot-note6---redisSpringbootRedis
- Spring Boot (十三): Spring Boot 小技巧Spring Boot
- Spring Boot 學習資料 (轉載)Spring Boot
- Spring Boot 學習筆記(3):MyBatisSpring Boot筆記MyBatis
- Spring boot + Zookeeper + Dubbo學習筆記Springboot筆記
- Java Spring Boot 學習筆記(一)JavaSpring Boot筆記
- Spring Boot學習資料彙總Spring Boot
- 快速學習 Spring Boot 技術棧Spring Boot
- Spring Boot學習筆記---Spring Boot 基礎及使用idea搭建專案Spring Boot筆記Idea
- Spring Boot:Spring Boot配置SwaggerSpring BootSwagger
- Spring Boot 2.0(八):Spring Boot 整合 MemcachedSpring Boot
- Spring Boot 參考指南(Spring Boot文件)Spring Boot
- Spring Boot(十八):使用 Spring Boot 整合 FastDFSSpring BootAST
- Spring Boot(五):Spring Boot Jpa 的使用Spring Boot
- Jeecg-Boot Spring BootSpring Boot