spring-day04
一. 事务
1.事务的作用:
- 当数据库操作序列中个别操作失败时,提供一种方式使数据库状态恢复到正常状态(A),保障数据库 即使在异常状态下仍能保持数据一致*©(要么操作前状态,要么操作后状态)。
- 当出现并发访问数据库时,在多个访问间进行相互隔离,防止并发访问操作结果互相干扰(I)。
2. 事务的基本特性有哪些?(面试题)
- ACID
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
3. 当前的数据出问题的情况?(面试题)
-
**脏读:**读到了另一个事务中未提交的数据
-
**不可重复读:**在一个事务中第一次读取到了一个数据,然后另一个事务对该行数据进行了修改,然后第一个事务再次读取此时数据就发生了变化
-
**幻读/虚读:**第一个事务读取了一次数据,然后另一个事务不断的删除/修改/新增数据,然后第一个事务再次读取数据,此时发现部分数据被删除部分数据被修改部份数据新增
4. 数据库的隔离级别有哪些,分别解决了什么问题(面试题)
-
读未提交
-
**读已提交:**解决了脏读的问题
-
**可以重复度:**解决了不可重复度的问题
-
**序列化:**解决所有的问题
二. xml实现spring的声明式事务管理
1. 在xml中导入tx的命名空间
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
2. 创建DataSourceTransactionManager并且注入一个dataSource对象
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
- 该对象只能用于jdbc和mybatis框架
3. 申明事务如何控制
<tx:advice id="txAdvice" transaction-manager="txManager">
<!--定义控制的事务-->
<tx:attributes>
<tx:method name="*" read-only="false"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
4. 使用aop把事务和业务结合起来
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.itheima.service.*Service.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
三. 声明的具体配置
<tx:method
name="transfer"
read-only="false"
timeout="-1"
isolation="DEFAULT"
no-rollback-for=""
rollback-for=""
propagation="REQUIRED"
/>
-
事务名称:name="*"
-
读写属性:read-only=“false”
-
隔离级别:isolation=“DEFAULT”
-
传播机制:propagation=“REQUIRED”
四. 注解实现声明式事务管理
1. 在xml中开启声明式事务观管理
-
- 创建一个管理者
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
-
- 开启
<tx:annotation-driven transaction-manager="txManager"/>
2. 在类上/方法上/接口上添加@Transactional注解
-
- 添加在类上或者接口上
-
类里面的所有的方法/接口里面的所有的方法使用统一的配置
//对当前方法添加事务,该配置将替换接口的配置 @Transactional( readOnly = false, timeout = -1, isolation = Isolation.DEFAULT, rollbackFor = {}, //java.lang.ArithmeticException.class, IOException.class noRollbackFor = {}, propagation = Propagation.REQUIRED ) public void transfer(String outName, String inName, Double money); }
-
- 配置在方法上-只有当前的方法使用该配置
-
- 推荐把注解配置在接口上同时接口上和方法上都配置
-
- 需要配置哪些内容
- readOnly = false,
- isolation = Isolation.DEFAULT,
- propagation = Propagation.REQUIRES
3. 纯注解是实现
-
-
在主配置类上添加@EnableTransactionManagement
@EnableTransactionManagement public class SpringConfig { }
-
-
-
在某一个配置类中创建一个bean-PlatformTransactionManager
@Bean public PlatformTransactionManager getTransactionManager(DataSource dataSource){ return new DataSourceTransactionManager(dataSource); }
-
4. redisTemplate
1. redisTemplate在写入数据到redis的时候会对key进行编码,如果换了客户端(jedis)那么就不能获取到数据,此时需要统一key的格式
-
1.创建Redis配置类
@PropertySource("redis.properties") public class RedisConfig { @Value("${redis.host}") private String hostName; @Value("${redis.port}") private Integer port; //配置redis访问密码 //@Value("${redis.password}") //private String password; @Value("${redis.maxActive}") private Integer maxActive; @Value("${redis.minIdle}") private Integer minIdle; @Value("${redis.maxIdle}") private Integer maxIdle; @Value("${redis.maxWait}") private Integer maxWait; @Bean //配置RedisTemplate public RedisTemplate createRedisTemplate(RedisConnectionFactory redisConnectionFactory){ //1.创建对象 RedisTemplate redisTemplate = new RedisTemplate(); //2.设置连接工厂 redisTemplate.setConnectionFactory(redisConnectionFactory); //3.设置redis生成的key的序列化器,对key编码进行处理 RedisSerializer stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setHashKeySerializer(stringSerializer); //4.返回 return redisTemplate; } @Bean //配置Redis连接工厂 public RedisConnectionFactory createRedisConnectionFactory(RedisStandaloneConfiguration redisStandaloneConfiguration,GenericObjectPoolConfig genericObjectPoolConfig){ //1.创建配置构建器,它是基于池的思想管理Jedis连接的 JedisClientConfiguration.JedisPoolingClientConfigurationBuilder builder = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder)JedisClientConfiguration.builder(); //2.设置池的配置信息对象 builder.poolConfig(genericObjectPoolConfig); //3.创建Jedis连接工厂 JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration,builder.build()); //4.返回 return jedisConnectionFactory; } @Bean //配置spring提供的Redis连接池信息 public GenericObjectPoolConfig createGenericObjectPoolConfig(){ //1.创建Jedis连接池的配置对象 GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); //2.设置连接池信息 genericObjectPoolConfig.setMaxTotal(maxActive); genericObjectPoolConfig.setMinIdle(minIdle); genericObjectPoolConfig.setMaxIdle(maxIdle); genericObjectPoolConfig.setMaxWaitMillis(maxWait); //3.返回 return genericObjectPoolConfig; } @Bean //配置Redis标准连接配置对象 public RedisStandaloneConfiguration createRedisStandaloneConfiguration(){ //1.创建Redis服务器配置信息对象 RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); //2.设置Redis服务器地址,端口和密码(如果有密码的话) redisStandaloneConfiguration.setHostName(hostName); redisStandaloneConfiguration.setPort(port); //redisStandaloneConfiguration.setPassword(RedisPassword.of(password)); //3.返回 return redisStandaloneConfiguration; } }
-
- Service层注入RedisTemplate,调用Redis操作数据
@Service("accountService") public class AccountServiceImpl implements AccountService { @Autowired private RedisTemplate redisTemplate; public void save(Account account) { } public void changeMoney(Integer id, Double money) { //等同于redis中set account:id:1 100 redisTemplate.opsForValue().set("account:id:"+id,money); } public Double findMondyById(Integer id) { //等同于redis中get account:id:1 Object money = redisTemplate.opsForValue().get("account:id:" + id); return new Double(money.toString()); } }
RedisTemplate对象结构
2. 常用各种数据类型的具体操作(掌握)
- redisTemplate.opsForValue().;
- redisTemplate.opsForHash().;
- redisTemplate.opsForList().;
- redisTemplate.opsForSet().;
- redisTemplate.opsForZSet();