事物知识点回顾
事物的四个特征
原子性(Atomicity)指事务是一个不可分割的整体,其中的操作要么全执行或全不执行
一致性(Consistency)事务前后数据的完整性必须保持一致
隔离性(Isolation)事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其任何影响
事物的四个隔离级别
读未提交(read-uncommitted) ,会造成脏读
不可重复读(read-committed) ,会造成不可重复度 oracle默认
可重复读(repeatable-read) ,会造成幻读 mysql默认
串行化(serializable)
脏读:表示读取未提交的数据,解决方案 read commited
不可重复度:两次读取到的数据不一致,原因是你在读取的时候,别人修改。解决方案 repeatable-read
幻读:两次读取到的数据条数不一致,原因是你在读取的时候,别人添加或者删除了数据。解决方案serializable
编程式事务控制相关对象
PlatformTransactionManager 接口是 spring 的事务管理器,它里面提供了我们常用的操作事务的方法。
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/2.png)
注意:
PlatformTransactionManager 是接口类型,不同的 Dao 层技术则有不同的实现类,例如:Dao 层技术是jdbc 或 mybatis 时:org.springframework.jdbc.datasource.DataSourceTransactionManager
Dao 层技术是hibernate时:org.springframework.orm.hibernate5.HibernateTransactionManager
- DataSourceTransactionManager 适用于Spring JDBC或MyBatis
- HibernateTransactionManager 适用于Hibernate3.0及以上版本
- JpaTransactionManager 适用于JPA
- JdoTransactionManager 适用于JDO
- JtaTransactionManager 适用于JTA
TransactionDefinition
TransactionDefinition 是事务的定义信息对象,里面有如下方法:
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/3.png)
事务隔离级别
设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读。
- ISOLATION_DEFAULT
- ISOLATION_READ_UNCOMMITTED
- ISOLATION_READ_COMMITTED
- ISOLATION_REPEATABLE_READ
- ISOLATION_SERIALIZABLE
事务传播行为
- REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
- SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
- MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
- REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
- NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
- NEVER:以非事务方式运行,如果当前存在事务,抛出异常
- NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作
- 超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
- 是否只读:建议查询时设置为只读
TransactionStatus
TransactionStatus 接口提供的是事务具体的运行状态,方法介绍如下。
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/4.png)
声明式事物
概念
声明式事物 = AOP+编程式事物
开发步骤
1.引入事物管理器
2.配置哪些方法使用事物
3.将通知类 和 切入点表达式结合 配置成切面(通知类是框架提供的)
XML配置声明式事务的开发步骤
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/1592807200564.png)
配置平台事物管理器
1 2 3 4
| <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
|
为spring提供的通知配置对应的配置信息,指定哪些方法需要被如何增强
1 2 3 4 5 6
| <tx:advice transaction-manager="dataSourceTransactionManager" id="transactionInterceptor"> <tx:attributes> <tx:method name="find*" isolation="DEFAULT" read-only="true" propagation="REQUIRED" /> </tx:attributes> </tx:advice>
|
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/1591367291135.png)
将spring提供的通知和切点织到一块
1 2 3
| <aop:config> <aop:advisor advice-ref="transactionInterceptor" pointcut="execution(* cn.itcast.service..*.*(..))"></aop:advisor> </aop:config>
|
半注解配置声明式事务的开发步骤
1.开启扫描
2.开启支持事物注解的驱动<tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven>
3.Service层加@Service,要使用事物的方法加@Transactional
配置平台事物管理器
1 2 3 4
| <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
|
在需要启用事务的方法或者类上加@Transactional注解
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/1592753041464.png)
启用注解配置事务
1 2 3 4
| <tx:annotation-driven></tx:annotation-driven>
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
|
全注解配置声明式事务的开发步骤
配置平台事物管理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package cn.itcast.config;
import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class TMConfig { @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(@Autowired DataSource dataSource){ SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); sqlSessionFactoryBean.setTypeAliasesPackage("cn.itcast.domain"); return sqlSessionFactoryBean; }
@Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("cn.itcast.dao"); return mapperScannerConfigurer; } }
|
需要启用事务的方法或者类上加@Transactional注解
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/1592753041464.png)
启用注解配置事务
1 2 3 4 5 6 7 8 9 10 11 12
| package cn.itcast.config;
import org.springframework.context.annotation.*; import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration @ComponentScan("cn.itcast") @EnableAspectJAutoProxy @EnableTransactionManagement @Import({DBConfig.class,MyBatisConfig.class,TMConfig.class}) public class SpringConfig { }
|
模板对象
Spring模块对象
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/1591368087398.png)
- TransactionTemplate
- JdbcTemplate
- RedisTemplate
- RabbitTemplate
- JmsTemplate
- HibernateTemplate
- RestTemplate
JdbcTemplate
JdbcTemplate是spring框架中提供的一个对象,是对原始繁琐的Jdbc API对象的简单封装。spring框架为我们提供了很多的操作模板类。例如:操作关系型数据的JdbcTemplate和HibernateTemplate,操作nosql数据库的RedisTemplate,操作消息队列的JmsTemplate等等。
JdbcTemplate基本使用-开发步骤(理解)
①导入spring-jdbc和spring-tx坐标
②创建数据库表和实体
③创建JdbcTemplate对象
④执行数据库操作
JdbcTemplate基本使用-快速入门代码实现
导入spring-jdbc和spring-tx坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.itheima</groupId> <artifactId>itheima_spring_jdbc</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging>
<name>itheima_spring_jdbc Maven Webapp</name> <url>http://www.example.com</url> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.2.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.3</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.5.RELEASE</version> </dependency> </dependencies> </project>
|
创建数据库表和实体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package com.itheima.domain;
public class Account {
private String name; private double money;
public String getNa me() { return name; }
public void setName(String name) { this.name = name; }
public double getMoney() { return money; }
public void setMoney(double money) { this.money = money; }
@Override public String toString() { return "Account{" + "name='" + name + '\'' + ", money=" + money + '}'; } }
|
创建JdbcTemplate对象
执行数据库操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Test public void test1() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); dataSource.setUser("root"); dataSource.setPassword("root");
JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); int row = jdbcTemplate.update("insert into account values(?,?)", "tom", 5000); System.out.println(row);
}
|
JdbcTemplate基本使用-spring产生模板对象分析(理解)
我们可以将JdbcTemplate的创建权交给Spring,将数据源DataSource的创建权也交给Spring,在Spring容器内部将数据源DataSource注入到JdbcTemplate模版对象中,然后通过Spring容器获得JdbcTemplate对象来执行操作。
JdbcTemplate基本使用-spring产生模板对象代码实现(应用)
配置如下:
1 2 3 4 5 6 7 8 9 10 11 12
| <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///test"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean>
|
测试代码
1 2 3 4 5 6 7 8
| @Test public void test2() throws PropertyVetoException { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); JdbcTemplate jdbcTemplate = app.getBean(JdbcTemplate.class); int row = jdbcTemplate.update("insert into account values(?,?)", "lisi", 5000); System.out.println(row); }
|
JdbcTemplate基本使用-spring产生模板对象代码实现(抽取jdbc.properties)
将数据库的连接信息抽取到外部配置文件中,和spring的配置文件分离开,有利于后期维护
1 2 3 4
| jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test jdbc.username=root jdbc.password=root
|
配置文件修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean>
</beans>
|
JdbcTemplate基本使用-常用操作-更新操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package com.itheima.test;
import com.itheima.domain.Account; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class JdbcTemplateCRUDTest {
@Autowired private JdbcTemplate jdbcTemplate; @Test public void testUpdate(){ jdbcTemplate.update("update account set money=? where name=?",10000,"tom"); } @Test public void testDelete(){ jdbcTemplate.update("delete from account where name=?","tom"); }
}
|
JdbcTemplate基本使用-常用操作-查询操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| package com.itheima.test;
import com.itheima.domain.Account; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class JdbcTemplateCRUDTest {
@Autowired private JdbcTemplate jdbcTemplate; @Test public void testQueryCount(){ Long count = jdbcTemplate.queryForObject("select count(*) from account", Long.class); System.out.println(count); } @Test public void testQueryOne(){ Account account = jdbcTemplate.queryForObject("select * from account where name=?", new BeanPropertyRowMapper<Account>(Account.class), "tom"); System.out.println(account); } @Test public void testQueryAll(){ List<Account> accountList = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class)); System.out.println(accountList); }
}
|
RedisTemplate
开发步骤
引入依赖
1 2 3 4 5 6 7 8 9 10 11 12
| <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.3</version> </dependency>
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.7.2.RELEASE</version> </dependency>
|
配置JedisTemplate Bean
xml版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="1" /> <property name="maxTotal" value="5" /> <property name="blockWhenExhausted" value="true" /> <property name="maxWaitMillis" value="30000" /> <property name="testOnBorrow" value="true" /> </bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="localhost" /> <property name="port" value="6379"/> <property name="poolConfig" ref="jedisPoolConfig" /> <property name="usePool" value="true"/> </bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean>
|
注解版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| package com.itheima.config;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisClientConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
@PropertySource("redis.properties") public class RedisConfig {
@Value("${redis.host}") private String hostName;
@Value("${redis.port}") private Integer port;
@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 public RedisTemplate createRedisTemplate(RedisConnectionFactory redisConnectionFactory){ RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(redisConnectionFactory); RedisSerializer stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setHashKeySerializer(stringSerializer); return redisTemplate; }
@Bean public RedisConnectionFactory createRedisConnectionFactory(RedisStandaloneConfiguration redisStandaloneConfiguration,GenericObjectPoolConfig genericObjectPoolConfig){ JedisClientConfiguration.JedisPoolingClientConfigurationBuilder builder = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder)JedisClientConfiguration.builder(); builder.poolConfig(genericObjectPoolConfig); JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration,builder.build()); return jedisConnectionFactory; }
@Bean public GenericObjectPoolConfig createGenericObjectPoolConfig(){ GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); genericObjectPoolConfig.setMaxTotal(maxActive); genericObjectPoolConfig.setMinIdle(minIdle); genericObjectPoolConfig.setMaxIdle(maxIdle); genericObjectPoolConfig.setMaxWaitMillis(maxWait); return genericObjectPoolConfig; }
@Bean public RedisStandaloneConfiguration createRedisStandaloneConfiguration(){ RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(hostName); redisStandaloneConfiguration.setPort(port);
return redisStandaloneConfiguration; }
}
|
编写测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class AccountServiceImplTest {
@Autowired private RedisTemplate redisTemplate;
@Test public void set(){ redisTemplate.opsForValue().set("age","45"); } @Test public void get(){ Object age = redisTemplate.opsForValue().get("age"); System.out.println(age); } }
|
RedisTemplate对象结构
(https://gitee.com/haoyongliang/resources/raw/master/images/spring/spring04事物/1591368270508.png)
1 2 3 4 5 6 7
| public void changeMoney(Integer id, Double money) { redisTemplate.opsForValue().set("account:id:"+id,money); } public Double findMondyById(Integer id) { Object money = redisTemplate.opsForValue().get("account:id:" + id); return new Double(money.toString()); }
|
String类型相关操作
1、获取缓存
1 2 3 4 5 6 7 8
|
public Object get(String key){ return key==null?null:redisTemplate.opsForValue().get(key); }
|
2、添加缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
public boolean set(String key,Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; }
}
|
3、添加缓存并设置过期时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public boolean set(String key,Object value,long time){ try { if(time>0){ redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); }else{ set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
4、递增操作
1 2 3 4 5 6 7 8 9 10 11
|
public long incr(String key, long delta){ if(delta<0){ throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); }
|
5、递减操作
1 2 3 4 5 6 7 8 9 10 11
|
public long decr(String key, long delta){ if(delta<0){ throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); }
|
哈希类型相关操作
1、设置一组Map的键值对
1 2 3 4 5 6 7 8 9
|
public Object hget(String key,String item){ return redisTemplate.opsForHash().get(key, item); }
|
2、获取指定Map的所有键值对
1 2 3 4 5 6 7 8
|
public Map<Object,Object> hmget(String key){ return redisTemplate.opsForHash().entries(key); }
|
3、添加一个Map类型值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public boolean hmset(String key, Map<String,Object> map){ try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
4、添加一个Map类型值并设置过期时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public boolean hmset(String key, Map<String,Object> map, long time){ try { redisTemplate.opsForHash().putAll(key, map); if(time>0){ expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
5、 向一张hash表中放入数据,如果不存在将创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
public boolean hset(String key,String item,Object value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
6、向一张hash表中放入数据,如果不存在将创建并设置过期时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public boolean hset(String key,String item,Object value,long time) { try { redisTemplate.opsForHash().put(key, item, value); if(time>0){ expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
7、删除hash表中的值
1 2 3 4 5 6 7 8
|
public void hdel(String key, Object... item){ redisTemplate.opsForHash().delete(key,item); }
|
8、判断hash表中是否有该项的值
1 2 3 4 5 6 7 8 9
|
public boolean hHasKey(String key, String item){ return redisTemplate.opsForHash().hasKey(key, item); }
|
9、递增,如果不存在,就会创建一个 并把新增后的值返回
1 2 3 4 5 6 7 8 9 10
|
public double hincr(String key, String item,double by){ return redisTemplate.opsForHash().increment(key, item, by); }
|
10、递减
1 2 3 4 5 6 7 8 9 10
|
public double hdecr(String key, String item,double by){ return redisTemplate.opsForHash().increment(key, item,-by); }
|
SET类型相关操作
1、根据key获取Set中的所有值
1 2 3 4 5 6 7 8 9 10 11 12 13
|
public Set<Object> sGet(String key){ try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } }
|
2、根据value从一个set中查询,是否存在
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public boolean sHasKey(String key,Object value){ try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } }
|
3、添加一个SET缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public long sSet(String key, Object...values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } }
|
4、添加一个SET缓存并设置过期时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public long sSetAndTime(String key,long time,Object...values) { try { Long count = redisTemplate.opsForSet().add(key, values); if(time>0) expire(key, time); return count; } catch (Exception e) { e.printStackTrace(); return 0; } }
|
5、获取SET缓存的长度
1 2 3 4 5 6 7 8 9 10 11 12 13
|
public long sGetSetSize(String key){ try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } }
|
6、移除指定key的缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public long setRemove(String key, Object ...values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } }
|
LIST类型相关操作
1、获取list缓存的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public List<Object> lGet(String key,long start, long end){ try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } }
|
2、 获取list缓存的长度
1 2 3 4 5 6 7 8 9 10 11 12 13
|
public long lGetListSize(String key){ try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } }
|
3、通过索引 获取list中的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public Object lGetIndex(String key,long index){ try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } }
|
4、 将list放入缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public boolean lSet(String key, Object value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
5、将list放入缓存并设置过期时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public boolean lSet(String key, Object value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
6、将list放入缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public boolean lSet(String key, List<Object> value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
7、将list放入缓存并设置过期时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public boolean lSet(String key, List<Object> value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
8、根据索引修改list中的某条数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
public boolean lUpdateIndex(String key, long index,Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
|
9、移除N个值为value
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
public long lRemove(String key,long count,Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } }
|
面试题
事物的四大特性ACID分别是什么
- 原子性
- 一致性
- 隔离性
- 持久性
事物的四个隔离级别是什么,mysql默认哪个隔离级别
- 脏读 读取未提交的数据
- 不可重复读 ,读已经提交的数据,读的时候允许别的事物修改,导致两次读取到数据不一样
- 幻读 读取已经提交的数据,读取的时候允许别的事物增删,导致两次读取到的数据个数不一样
- 串行化
mysql默认的是Repeatable
事物的传播行为有哪些
默认是REQUIRED
REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
REQUIRES_NEW:它会开启一个新的事务。如果一个事务已经存在,则先将这个存在的事务挂起。
SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。
NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务。
MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
NEVER:总是非事务地执行,如果存在一个活动事务,则抛出异常。
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。 这是一个嵌套事务