Springboot连接操作数据库

目录

 

一、整合JDBC相关配置

二、Druid连接池与监控管理

自定义配置数据源连接池

配置Druid监控

三、整合MyBatis

mybatis使用注解方式

使用xml配置文件

四、整合SpringDataJPA

五、Springboot事务管理

六、事务的隔离级别和传播行为


一、整合JDBC相关配置

pom.xml配置

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

application.yml配置

spring:
  datasource:
    #mysql驱动8.0及以上版本,要使用com.mysql.cj.jdbc.Driver驱动类
    driver-class-name: com.mysql.cj.jdbc.Driver
    #mysql驱动8.0及以上版本,url后面要加上时区,GMT%2B8表示中国时区,不然报时区错误
    url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8
    username: root
    password: 123

连接测试

@SpringBootTest
class SpringBoot05JdbcApplicationTests {
    @Autowired
    DataSource dataSource;
    @Test
    void contextLoads() throws SQLException {
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }
}

运行结果:

  • SpringBoot 默认采用的数据源连接池是:  com.zaxxer.hikari.HikariDataSource
  • 数据源相关配置都在 DataSourceProperties 中。

二、Druid连接池与监控管理

自定义配置数据源连接池

1.pom.xml引入Druid依赖

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>

2.application.yml配置数据源

spring:
  datasource:
    #mysql驱动8.0及以上版本,要使用com.mysql.cj.jdbc.Driver驱动类
    driver-class-name: com.mysql.cj.jdbc.Driver
    #mysql驱动8.0及以上版本,url后面要加上时区,GMT%2B8表示中国时区,不然报时区错误
    url: jdbc:mysql://127.0.0.1:3306/bill?serverTimezone=GMT%2B8
    username: root
    password: 123
    #指定druid数据源
    type: com.alibaba.druid.pool.DruidDataSource

    #数据源其他配置, DataSourceProperties中没有相关属性,需要手动配置
    initialSize: 8
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙  
    filters: stat,wall,logback
    maxPoolPreparedStatementPerConnectionSize: 25
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

3.通过配置类,将配置中的数据和DruidDatasource绑定

@Configuration
public class DruidfConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")//绑定数据源配置
    public DataSource druid(){
        return new DruidDataSource();
    }
}

配置Druid监控

@Configuration
public class DruidfConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")//绑定数据源配置
    public DataSource druid(){
        return new DruidDataSource();
    }

    //配置Druid监控
    //1.配置一个管理后台的Servlet
    @Bean
    public ServletRegistrationBean statViewServlet(){
        //请求路径以 /druid/ 开头都会去访问这个Servlet
        ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(),"/druid/*");
        //配置初始化参数
        Map<String,String> initParam = new HashMap<>();

        //访问的用户名密码
        initParam.put(StatViewServlet.PARAM_NAME_USERNAME,"root");
        initParam.put(StatViewServlet.PARAM_NAME_PASSWORD,"123");
        //允许访问的ip,默认所有ip访问
        initParam.put(StatViewServlet.PARAM_NAME_ALLOW,"");
        //禁止访问的ip
        initParam.put(StatViewServlet.PARAM_NAME_DENY,"192.168.11.1");

        bean.setInitParameters(initParam);
        return bean;
    }

    //2.配置一个监控的filter
    @Bean
    public FilterRegistrationBean filter(){
        FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new WebStatFilter());
        //配置初始化参数
        Map<String,String> initParam = new HashMap<>();
        //排除请求
        initParam.put(WebStatFilter.PARAM_NAME_EXCLUSIONS,"*.js,*.css,/druid/*");
        //拦截所有的请求
        bean.setUrlPatterns(Arrays.asList("/*"));
        return bean;
    }
}

登录druid监控系统

 

三、整合MyBatis

创建项目时勾选mybatis框架

添加mybatis依赖

        <!--导入mybatis启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>

mybatis使用注解方式

1.创建实体类和mapper接口

//指定这是操作数据的Mapper,或使用在配置类使用@MapperScan(mapper包名)注解扫描
@Mapper
public interface ProviderMapper {
    /**
     * useGeneratedKeys:是否使用主键自增长
     * keyProperty:对应实体类中主键的属性
     */
    @Options(useGeneratedKeys = true, keyProperty = "pid")
    @Insert("insert into provider(providerName)values(#{providerName})")
    int addProvider(Provider provider);

    @Delete("delete from provider where pid=#{pid}")
    int deleteProvide(Integer pid);

    @Update("update provider set providerName=#{providerName} where pid=#{pid}")
    int updateProvider(Provider provider);

    @Select("select * from provider where pid=#{pid}")
    Provider getProvider(Integer pid);
}

2.使用驼峰命名方式,把数据库字段如:provider_name自动转成providerName

@Configuration
public class MybatisConfig {
    @Bean
    public ConfigurationCustomizer configurationCustomizer(){
        return new ConfigurationCustomizer() {
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {
                //开启驼峰命名方式
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}

3.添加Controller测试

@Controller
public class ProviderController {
    @Autowired
    private ProviderMapper providerMapper;

    @ResponseBody
    @GetMapping("/provider/{pid}")
    public Provider getProvider(@PathVariable("pid")Integer pid){
        Provider provider = providerMapper.getProvider(pid);
        return provider;
    }
    @GetMapping("/add")
    public Provider addProvider(Provider provider){
        System.out.println(provider);
        providerMapper.addProvider(provider);
        return provider;
    }
}

使用xml配置文件

1.mapper接口

@Mapper
public interface BillMapper {
    Bill getBill(Integer bid);
    int getBill(Bill bill);
}

2.在resources目录下创建mybatis核心配置文件和mapper映射文件

MybatisConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--mybatis核心配置-->
    <settings>
        <!--开启驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>

映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mxg.springboot.mapper.BillMapper">
    <select id="getBill" resultType="com.mxg.springboot.entities.Bill" >
        select * from bill where bid=#{bid}
    </select>
    <insert id="addBill" parameterType="com.mxg.springboot.entities.Bill">
        insert into bill(bill_code,bill_name)values(#{billCode},#{billName})
    </insert>
</mapper>

3.application.yml指定mybatis配置文件路径

mybatis:
  #核心配置文件路径
  config-location: classpath:mybatis/MybatisConfig.xml
  #映射配置文件路径
  mapper-locations: classpath:mybatis/mapper/*.xml

4.添加Controller测试

@Controller
public class BillController {
    @Autowired
    private BillMapper billMapper;

    @ResponseBody
    @GetMapping("/bill/{bid}")
    public Bill getBill(@PathVariable("bid") Integer bid){
        return billMapper.getBill(bid);
    }
    @GetMapping("/bill")
    public Bill addBill(Bill bill){
        billMapper.addBill(bill);
        return bill;
    }
}

四、整合SpringDataJPA

JPA 的底层遵守是 ORM( 对象关系映射 ) 规范,因此 JPA 其实也就是 java 实体对象和关系型数据库建立起映射关系,通过面向对象编程的思想操作关系型数据库的规范
 
1. 在application全局配置文件配置JPA
spring:
  datasource:
    #mysql驱动8.0及以上版本,要使用com.mysql.cj.jdbc.Driver驱动类
    driver-class-name: com.mysql.cj.jdbc.Driver
    #mysql驱动8.0及以上版本,url后面要加上时区,GMT%2B8表示中国时区,不然报时区错误
    url: jdbc:mysql://127.0.0.1:3306/jpa?serverTimezone=GMT%2B8
    username: root
    password: 123

  #Jpa相关配置sping.jpa.*
  jpa:
    #控制台显示SQL
    show-sql: true
    hibernate:
      #会根据映射实体类自动创建或更新数据表
      ddl-auto: update #update:创建和更新  create:只创建
    #默认创建表类型是MyISAM,是非事务安全的,所以无法实现事务回滚
    #指定如下:创建的表类型是Innodb,才可以进行对事务的回滚
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
2.  创建实体类,并使用 JPA 注解进行配置映射关系
//使用JPA注解进行配置映射关系
@Entity //说明它是和数据表映射的类
@Table(name = "tb_user")//指定对应映射的表名,省略默认表名就是类名
public class User {
    @Id //标识为主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)//标识主键自增长
    private Integer id;
    
    //指定对应数据表的列的字段名,length限制最大长度为5
    @Column(name = "user_name", length = 5)
    private String username;

    //默认表的字段名和属性名一样
    @Column
    private String password;

    //指定数据库生成时间方式(类型TemporalType.TIMESTAMP:日期+时间)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createTime;
    //省略get/set方法
}

3. 创建 UserRepository 接口继承 JpaRepository 

/**
 * 自定义接口继承JpaRepository,就有crud及分页等基本功能
 */
public interface UserRepository extends JpaRepository<User, Integer> { //指定的泛型<操作的实体类,主键类型>
}

4. 添加controller测试

@RestController
public class UserController {
    @Autowired
    private UserRepository userRepository;
    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable("id") Integer id){
        Optional<User> user = userRepository.findById(id);
        return user.get();
    }
    @GetMapping("/user")
    public User addUser(User user){
        return userRepository.save(user);
    }
}

五、Springboot事务管理

Spring Boot 中,当我们使用了 spring-boot-starter-jdbc spring-boot-starter-data-jpa依赖的时候,框架会自动默认分别注入 DataSourceTransactionManager JpaTransactionManager。所以我们不需要任何额外配置就可以用 @Transactional 注解进行事务的使用
 
注意:Hibernate创建数据库表时
  • 默认创建表类型是MyISAM,是非事务安全的,所以无法实现事物回滚; Innodb才可以进行对事物的回滚
  • (具体在上面整合JPA第3步)需要指定spring.jpa.database-platform=org.hibernate.dialect.MySQL57Dialect

1.在启动类上,使用@EnableTransactionManagement开启注解方式事务支持

@EnableTransactionManagement
@SpringBootApplication
public class SpringBootJpaApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootJpaApplication.class, args);
    }
}

2.在Service层添加@Transactional注解进行事务管理

@Service
public class AccountServiceImpl implements IAccountService {
    @Autowired
    private AccoutRepository accoutRepository;

    @Transactional//事务管理注解
    @Override
    public Boolean transfer(Account from, Account to, double money) {
        from.setMoney(from.getMoney() - money);
        accoutRepository.save(from);

        int a = 1/0;//模拟错误

        to.setMoney(to.getMoney() + money);
        accoutRepository.save(to);
        return true;
    }
}

六、事务的隔离级别和传播行为

隔离问题:

  • 脏读:A事务执行过程中修改了id=1的数据,未提交前,B事务读取了A修改的id=1的数据,而A事务却回滚了,这样B事务就形成了脏读
  • 不可重复读:A事务先读取了一条数据,然后执行逻辑的时候,B事务将这条数据改变了,然后A事务再次读取的时
    候,发现数据不匹配了,就是所谓的不可重复读了
  • 幻读:A事务先根据条件查询到了N条数据,然后B事务新增了M条符合A事务查询条件的数据,导致A事务再次查询
    发现有N+M条数据了,就产生了幻读

隔离级别:

  • SERIALIZABLE(串行化):能解决3种读问题,非并发访问,性能最差
  • READ_COMMITTED(读已提交数据):表示一个事务只能读取已提交的数据,可防止脏读(一般用这个)
  • REPEATABLE_READ(可重复读):表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。可以防止脏读和不可重复读
  • READ_UNCOMMITTED(读未提交数据):不做任何处理,可能出现任何事务并发问题
  • ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;

指定方式:通过isolation属性设置

@Transactional(isolation = Isolation.READ_COMMITTED)

传播行为:

  • REQUIRED :(默认)如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  • SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • MANDATORY :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  • REQUIRES_NEW :创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • NOT_SUPPORTED :以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。
  • NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED

指定方式:通过propagation属性设置

@Transactional(propagation = Propagation.REQUIRED)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值