事物知识点回顾
事物的四个特征
原子性(Atomicity)指事务是一个不可分割的整体,其中的操作要么全执行或全不执行
一致性(Consistency)事务前后数据的完整性必须保持一致
隔离性(Isolation)事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其任何影响
事物的四个隔离级别
 读未提交(read-uncommitted) ,会造成脏读
 不可重复读(read-committed) ,会造成不可重复度 oracle默认
 可重复读(repeatable-read) ,会造成幻读 mysql默认
 串行化(serializable) 
脏读:表示读取未提交的数据,解决方案 read commited
不可重复度:两次读取到的数据不一致,原因是你在读取的时候,别人修改。解决方案 repeatable-read
幻读:两次读取到的数据条数不一致,原因是你在读取的时候,别人添加或者删除了数据。解决方案serializable
编程式事务控制相关对象
PlatformTransactionManager 接口是 spring 的事务管理器,它里面提供了我们常用的操作事务的方法。

注意:
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 是事务的定义信息对象,里面有如下方法:

 事务隔离级别
设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读。
 事务传播行为
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
 
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
 
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
 
REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
 
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
 
NEVER:以非事务方式运行,如果当前存在事务,抛出异常
 
NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作
 
超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
 
是否只读:建议查询时设置为只读
 
TransactionStatus
TransactionStatus 接口提供的是事务具体的运行状态,方法介绍如下。

声明式事物
概念
声明式事物 = AOP+编程式事物
开发步骤
1.引入事物管理器
2.配置哪些方法使用事物
3.将通知类 和 切入点表达式结合 配置成切面(通知类是框架提供的)
XML配置声明式事务的开发步骤

配置平台事物管理器
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>
 
  | 
 

将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注解

启用注解配置事务
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注解

启用注解配置事务
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模块对象

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 19
   |  @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对象结构

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 属性执行。 这是一个嵌套事务