spring全家桶之Jdbc必知必会的内容

正在学习丁雪丰大大的Spring全家桶

如何快速的创建Spring boot项目?

可以通过start.spring.io创建Spring boot的骨架
在这里插入图片描述

选择项目、语言、版本、填写项目元数据内容、添加依赖
完成后,下载生成zip文件,导入项目即可

使用idea如下配置:
在这里插入图片描述
可能会提示连接失败,重试几次即可。
在这里插入图片描述
配置项目信息
选择依赖
然后点下一步配置项目名与地址就可以直接在idea中打开

如何运行Spring Boot?

方法一
在SpringBootApplication中直接运行
方法二
通过maven命令导出jar包

mvn clean package -Dmaven.test.skip
java -jar ***.jar 执行jar包

第二种方式在生产、测试环境中运行比较方便。

创建单数据源

创建项目时选择数据库对应的依赖
配置properties,完成后,springboot会自动帮我们配置好dataSource、事务(transaction)等
也可以配置sql文件,项目启动后,自动建表以及添加数据。

创建多个数据源

两个数据源的参数配置要分开!
如何区分数据源?
第一种:在dataSource加上@Primary注解
那SpringBoot 就会在加了@Primary的bean中展开
分主次

第二种:如果没有主次之分的话
就排除一下SpringBoot的一些Bean的自动配置

DataSourceAutoConfiguration
DataSourceTransactionManagerAutoConfiguration
JdbcTemplateAutoConfiguration

然后自己在代码中控制哪个数据库对应哪个数据源

如何排除?
在注解@SpringBootApplication(exclude={DataSourceAutoConfiguration.class,DataSourceTransactionManagerAutoConfiguration.class,JdbcTemplateAutoConfiguration.class})

然后自己就得开始配置,DataSource、TransactionManager等

如何配置?
1.首先配置application.properties,配置数据库参数(这边使用的是H2内存数据库)

foo.datasource.url=jdbc:h2:mem:foo
foo.datasource.username=sa
foo.datasource.password=

bar.datasource.url = jdbc:h2:mem:bar
bar.datasource.username = sa
bar.datasource.password =

通过foo.datasource和bar.datasource前缀区分不同的参数
那么,要如何区分呢?
需要创建一个返回DataSourceProperties的方法
通过注解:

@ConfigurationProperties(“foo.datasource”)

自动去Properties文件中寻找对应的值foo.datasource.url等,自动赋值到DataSourceProperties中
然后使用

DataSourceProperties.initializeDataSourceBuilder().build();
构建一个DataSource并返回

用@Bean注解,告诉Spring生成一个Bean对象,这个Bean对象Spring只会调用一次,然后将这个Bean放到IoC容器中。
最后添加事务
前面已经把DataSource配置好了,这时就可以使用构造函数注入方式,将dataSource注入到事务中
使用@Bean @Resource,将事务的Bean放到IoC容器中

    @Bean
    @Resource
    public PlatformTransactionManager barTransactionManager(DataSource barDataSource){
        return new DataSourceTransactionManager(barDataSource);
    }

这样就配置好了多数据源的方式,根据项目方案,可自行配置多个数据源。

有哪些好用的连接池?

1.HikariCP(SpringBoot 2.x默认使用)
Hikari来源于日语,是“光”的意思,体现了HikariCP作者的起名意义,体现Hikari就是快!
在这里插入图片描述
It’s Faster

Hikari为什么会那么快?

1.字节码级别优化(很多方法通过JavaAssist生成)
2.大量小改进
1)使用FastStatementList替换ArrayList
2)无锁集合ConcurrentBag
3)代理类优化(比如:invokestatic代替了invodevirtual)

SpringBoot 1.x 默认使用Tomcat连接池,如果要使用HikariCP,需要移除Tomcat-jdbc依赖
再配置spring.datasource.type = com.zaxxer.hikari.HikariDataSource

在这边看一下Hikari数据源的源码
在这里插入图片描述
通过@ConditionalOnClass注解判断在classpath中有HikariDataSource这个类的时候,
并且@ConditionalOnMissingBean注解判断在Spring的上下文中,没有DataSource,最后用@ConditionalOnProperty判断在Properties中的spring.datasource.type的值是com.zaxxer.hikari.HikariDataSource的时候才调用Hikari数据源

然后通过@ConfigurationProperties注解获取属性前缀为spring.datasource.hikari,将参数都配置到DataSourceProperties中做初始化

常用的Hikari配置
spring.datasource.hikari.maximumPoolSize = 100
spring.datasource.hikari.minimumIdle = 10
spring.datasource.hikari.idleTimeout = 600000
spring.datasource.hikari.connectionTimeout = 80000
spring.datasource.hikari.maxLifetime = 1800000
其他详细配置:
https://github.com/brettwooldridge/HikariCP
在这里插入图片描述
2.Alibaba Druid
在这里插入图片描述
如果要使用Druid,那就最好将排除HikariCP

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
	<!-- 排除 HikariCP-->
	<exclusions>
		<exclusion>
			<groupId>com.zaxxer</groupId>
			<artifactId>HikariCP</artifactId>
		</exclusion>
	</exclusions>
</dependency>

Druid的优点有哪些呢?
1.Alibaba出品,经历过很多大系统的考验,安全可靠!
2.监控统计功能,很详细的监控
3.防SQL注入
4.内置密码加密
5.ExceptionSorter,针对主流数据库的返回码都有支持
(在Druid中,会根据连接池连接数据库的类型自动匹配不同类型的ExceptionSorter,不需要额外配置。这一点Druid和jboss是不同的。)

在这里插入图片描述
慢sql日志
系统属性配置
druid.stat.logShowSql = true
druid.stat.slowSqlMillis = 3000

String Boot
spring.datasource.druid.filter.stat.log-show-sql = true
spring.datasource.druid.filter.stat.slow-sql-millis = 300

如果有sql执行超过300ms,就报错

Druid Filter

用于定制连接池操作的各种环节
继承FilterEventAdapter,方便使用filter
配置META-INF的druid-filter.properties,用于增加filter配置

application.properties中配置Filter

spring.datasource.druid.filters=conn,config,stat,slf4j

其中conn就是自己增加的filter配置
这就需要配置druid-filter.properties

druid.filters.conn = com...ConnectionFilter

如何通过jdbc访问数据库?

可以通过JdbcTemplate进行访问

方法描述
queryForObject(sql,Class)查询数据库返回单个数据
queryForList(sql,Class)查询数据库,返回list
query(sql,new RowMapper(Object){})查询数据库,返回指定对象
update(sql,args)更新数据库,可进行update和insert操作

批量更新数据库有两种方法:
1.使用jdbcTemplate.batchUpdate

jdbcTemplate.batchUpdate("insert into default_tb(tname) values(?)", new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                ps.setString(1,"d-"+i);
            }

            @Override
            public int getBatchSize() {
                return 2;
            }
        });

2.使用 namedParameterJdbcTemplate.batchUpdate

List<Foo> foos = new ArrayList<Foo>();
foos.add(Foo.builder().id(123).name("123").build());
namedParameterJdbcTemplate.batchUpdate(sql,SqlParameterSourceUtils.createBatch(foos))

若要获取查询数据后直接Id的话,可以使用SimpleJdbcInsert
但是需要写一下实现方法

    @Bean
    @Autowired
    public SimpleJdbcInsert simpleJdbcInsert(JdbcTemplate jdbcTemplate){
        //withTableName  关联的table
        //usingGeneratedKeyColumns 使用的生成id字段
        return new SimpleJdbcInsert(jdbcTemplate).withTableName("default_tb").usingGeneratedKeyColumns("id");
    }
        Map<String,String> values = new HashMap<String,String>();
        values.put("tname","c");
        Number key = simpleJdbcInsert.executeAndReturnKey(values);
        log.info("c -> id = "+ key.intValue());

spring的事务抽象

事务有四大特征ACID
A:Atomicity(原子性)
原子的特性就是不可分割的,可以看做是组成物质的基本单位,也是我们对数据进行操作的基本单位。
C:Consistency(一致性)
无论事务提交或者回滚,对数据的完整性约束是不能改变的。即数据库进行事务操作后,会从一种一致性状态变为了另一种一致性状态。
I:Isolation(隔离性)
每个事务都是独立存在的,即每个事务提交前,对其他事务而言是不可见的。
D:Durability(持久性)
是通过事务日志进行保证的,日志包括了“回滚日志”、“重做日志”, 事务日志是“写前日志”,即在数据处理前,就将数据库变化的信息放入到重做日志中,这种方式保证了即使数据库宕机后,也能通过日志重新执行,从而保证了事务的持久性。
事务的传播特性

传播性描述
PROPAGATION_REQUIRED0当前有事务就用当前的,没有事务的话就用新的
PROPAGATION_SUPPORTS1事务可有可无,不是必须的
PROPAGATION_MANDATORY2当前一定要有事务,不然就抛异常
PROPAGATION_REQUIRES_NEW3无论是否有事务都启一个新的事务
PROPAGATION_NOT_SUPPORTED4不支持事务,按非事务的方式运行
PROPAGATION_NEVER5不支持事务,如果有事务就抛异常
PROPAGATION_NESTED6如果有事务就在当前的事务内再启一个事务(内嵌事务)

事务的隔离特性

隔离性描述
ISOLATION_READ_UNCOMMITTED1隔离级别最低,一个事务可以读到另一个事务未提交的结果,所有并发问题都有可能发生。
ISOLATION_READ_COMMITTED2可以解决脏读,但是不可重复读和幻读都存在
ISOLATION_REPEATABLE_READ3可以解决不可重复读和脏读,但是幻读还是存在
ISOLATION_SERIALIZAABLE4可以解决所有并发问题,但是效率低

脏读:事务B读取到了事务A未提交的数据,这时事务A提交失败了,事务B读取的数据就是脏数据。
不可重复读:使用同一条查询语句,前后两次查询的结果不一致。
幻读:同一条查询语句,前后两次查询集合的数量不一致。

若隔离级别越高,那么处理事务的效率越低。
这时因为,隔离级别越高,就越接近“串行化”,只有一个事务处理完,才会进行下一个事务的处理,这就肯定没有了并行的效率。
所以需要在正确性和性能之间做一个平衡。

编程式事务
TransactionTemplate

  • TransactionRollback (有返回值的rollback)
  • TransactionRollbackWithoutResult(没有返回值的rollback)
    PlatformTransactionManager
  • 可以传入TransactionDefinition进行定义
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                 jdbcTemplate.update("delete from foo");
                 log.info("after delete foo count->"+getCount());
                 transactionStatus.setRollbackOnly();
                 log.info("after rollback foo count->"+getCount());
            }
        });

声明式事务
在这里插入图片描述

基于注解的配置方式

开启事务的注解方式:

  • @EnableTransactionManagement
  • <tx-annotation-driven / >

能做以下配置:

  • proxyTargetClass 代理
  • mode
  • order 事务AOP拦截的顺序,默认最低优先级

@Transactional

  • propagation 配置传播特性
  • isolation 配置隔离特性
  • rollbackFor 配置遇到指定异常就回滚
  • transactionManager
  • readOnly
  • timeout
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值