您的位置:首页 > 编程语言 > Java开发

Spring Boot学习6:Spring Boot JDBC

2018-02-13 13:03 274 查看
1 数据源
数据源是数据库连接的来源,通过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("inse
4000
rt 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