springMVC整合jedis+redis,以注解形式使用

前两天写过 springMVC+memcached 的整合,我从这个基础上改造一下,把redis和springmvc整合到一起。

和memcached一样,redis也有java专用的客户端,官网推荐使用的是:jedis。

看了一部分资料,大家推荐使用 spring-data-redis (spring在jedis的基础上又包装了一层),但是实际中感觉写起来有点麻烦,不如原生态的jedis好用。

所以我利用spring的构造注入做了一个springmvc整合jedis的例子。

先了解下redis吧,这些资料袋都是从网上看到的:

Redis使用c语言编写,面向“键/值”对类型数据的分布式NoSql数据库系统。
目前提供五中数据类型
    string(字符串)
    list(链表)
    Hash(哈希)
    set(集合)
    zset(sorted set 有序集合),有2中编码类型:ziplist,skiplist,当zset中数据较多时,将会被重构为skiplist。
默认端口6379

redis-server.exe:服务端
 redis-check-dump.exe:本地数据库检查
 redis-check-aof.exe:更新日志检查
 redis-benchmark.exe:性能测试,用以模拟同时由N个客户端发送M个 SETs/GETs 查询.
 redis-cli.exe: 这个是客户端,服务端开启后,客户端就可以输入各种命令测试了

先写一个Test类,测一下redis的基本数据类型和jedis的一些常用方法。以下的测试方法也都是从网上看到的,只不过为了验证是否准确以及jar包版本的问题,我自己亲自敲了一遍。

注意jedis是redis的一个客户端,是个jar包,不要搞混了……

public class Test {

    public static void main(String[] args) {
//        Jedis js = new Jedis("127.0.0.1", 6379);

//        js.set("key001", "redis001");
//        String val = js.get("key001");
//        System.out.println(val);
//        js.del("key001");

/**************************测试Redis的数据类型**************************/

        /**
         * list
         */
//        js.rpush("list1", "aaaaaaaaaaaaaaaaaaaaaa");
//        js.rpush("list1", "bbbbbbbbbbbbbbbbbbbbbb");
//        js.rpush("list1", "ccccccccccccccccccccc");
//        js.rpush("list1", "dddddddddddddd");
//        List<String> vals = js.lrange("list1", 0, -1);
//        for (int i = 0; i < vals.size(); i++) {
//            System.out.println(vals.get(i));
//        }

        /**
         * set 无须唯一
         */
//        js.sadd("s1", "顺序3");
//        js.sadd("s1", "a");
//        js.sadd("s1", "b");
//        js.sadd("s1", "1");
//        js.sadd("s1", "蛤蛤蛤");
//        js.sadd("s1", "2");
//        js.sadd("s1", "so waht?");
//        js.sadd("s1", "%^");
//        js.sadd("s1", "顺序1");
//        js.sadd("s1", "乱码吗?");
//        js.sadd("s1", "顺序2");
//        Set<String> s = js.smembers("s1");
//        for (String string : s) {
//            System.out.println(s);
//        }
//        js.srem("s1", "蛤蛤蛤");

        /**
         * zset(sorted set 有序集合)
         * 有2中编码类型:ziplist,skiplist,当zset中数据较多时,将会被重构为skiplist
         */
//        js.zadd("zs", 92, "张三1");
//        js.zadd("zs", 93, "张三7");
//        js.zadd("zs", 94, "张三5");
//        js.zadd("zs", 87, "张三9");
//        js.zadd("zs", 66, "张三");
//        js.zadd("zs", 19, "张三0");
//        Set<String> sets = js.zrange("zs", 0, -1);
//        for (String string : sets) {
//            System.out.println(sets);
//        }

        /**
         * Hash
         */
//        Map m = new HashMap();
//        m.put("1", "t");
//        m.put("2", "ttt");
//        m.put("username", "老王");
//        m.put("password", "123456");
//        m.put("age", "79");
//        m.put("sex", "man");
//        js.hmset("m", m);
//        List<String> v = js.hmget("m", new String[]{"username","age"});
//        List<String> v1 = js.hmget("m", "sex");
//        System.out.println(v);
//        System.out.println(v1);
//        js.hdel("m", "username");//删除map中的某一个键的键值对

/**************************事务控制**************************/

        /**
         * 事务方式(Transactions)
         * 他主要目的是保障,一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。
         *
         * 我们调用jedis.watch(…)方法来监控key,如果调用后key值发生变化,则整个事务会执行失败。
         * 另外,事务中某个操作失败,并不会回滚其他操作。这一点需要注意。
         * 还有,我们可以使用discard()方法来取消事务。
         */
//        Jedis js1 = new Jedis("127.0.0.1", 6379);
//        long s = System.currentTimeMillis();
//        Transaction tx = js1.multi();
//        for (int i = 0; i < 99999; i++) {
//            tx.set("keyttt"+i, "valttt"+i);
//        }
//        List<Object> res= tx.exec();
//        long e = System.currentTimeMillis();
//        System.out.println((e-s)/1000.0+"秒");
        //System.out.println(res);
//        js1.disconnect();

/**************************管道**************************/
        /**
         * 管道(Pipelining)
         * 有时,我们需要采用异步方式,一次发送多个指令,不同步等待其返回结果。
         * 这样可以取得非常好的执行效率。这就是管道
         */
//        Jedis js2 = new Jedis("127.0.0.1", 6379);
//        long s = System.currentTimeMillis();
//        Pipeline pe = js2.pipelined();
//        for (int i = 0; i < 9999; i++) {
//            pe.set("keya"+i, "valuea"+i);
//        }
//        List<Object> l = pe.syncAndReturnAll();
//        long e = System.currentTimeMillis();
//        System.out.println((e-s)/1000.0+"秒");
//        js2.disconnect();

/**************************管道中调用事务**************************/
        /**
         * 管道中调用事务
         * 在用法上看,管道中包含了事务
         */

//        Jedis js3 = new Jedis("127.0.0.1", 6379);
//        long s = System.currentTimeMillis();
//        Pipeline pe = js3.pipelined();
//        pe.multi();
//        for (int i = 0; i < 9999; i++) {
//            pe.set("keybb"+i, "valuebb"+i);
//        }
//        pe.exec();
//        List<Object> l = pe.syncAndReturnAll();
//        long e = System.currentTimeMillis();
//        System.out.println((e-s)/1000.0+"秒");
//        js3.disconnect();        

/**************************分布式直连同步调用**************************/
        /**
         * 分布式直连同步调用
         * 线程不安全的,不建议在线程池中使用直连
         */
//        List<JedisShardInfo> shards = Arrays.asList(
//                new JedisShardInfo("localhost",6379),
//                new JedisShardInfo("localhost",6380));
//        ShardedJedis sharding = new ShardedJedis(shards);
//        long start = System.currentTimeMillis();
//        for (int i = 0; i < 100000; i++) {
//            String result = sharding.set("sn" + i, "n" + i);
//        }
//        long end = System.currentTimeMillis();
//        System.out.println("[email protected] SET: " + ((end - start)/1000.0) + " seconds");
//        sharding.disconnect();        

/**************************分布式直连同步调用**************************/
        /**
         * 分布式直连异步调用
         * 线程不安全的,不建议在线程池中使用直连
         */
//         List<JedisShardInfo> shards = Arrays.asList(
//                    new JedisShardInfo("localhost",6379),
//                    new JedisShardInfo("localhost",6380));
//            ShardedJedis sharding = new ShardedJedis(shards);
//            ShardedJedisPipeline pipeline = sharding.pipelined();
//            long start = System.currentTimeMillis();
//            for (int i = 0; i < 100000; i++) {
//                pipeline.set("sp" + i, "p" + i);
//            }
//            List<Object> results = pipeline.syncAndReturnAll();
//            long end = System.currentTimeMillis();
//            System.out.println("[email protected] SET: " + ((end - start)/1000.0) + " seconds");
//            sharding.disconnect();        

/**************************分布式连接池同步调用**************************/
            /**
             * 同步方式
             */
//            List<JedisShardInfo> shards = Arrays.asList(
//                    new JedisShardInfo("localhost",6379),
//                    new JedisShardInfo("localhost",6380));
//
//            ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);
//
//            ShardedJedis one = pool.getResource();
//
//            long start = System.currentTimeMillis();
//            for (int i = 0; i < 100000; i++) {
//                String result = one.set("spn" + i, "n" + i);
//            }
//            long end = System.currentTimeMillis();
//            pool.returnResource(one);
//            System.out.println("[email protected] SET: " + ((end - start)/1000.0) + " seconds");
//
//            pool.destroy();
//        

/**************************分布式连接池异步调用**************************/
        /**
         * 异步方式
         */
//         List<JedisShardInfo> shards = Arrays.asList(
//                    new JedisShardInfo("localhost",6379),
//                    new JedisShardInfo("localhost",6380));
//
//        ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);
//
//        ShardedJedis one = pool.getResource();
//
//        ShardedJedisPipeline pipeline = one.pipelined();
//
//        long start = System.currentTimeMillis();
//        for (int i = 0; i < 100000; i++) {
//            pipeline.set("sppn" + i, "n" + i);
//        }
//        List<Object> results = pipeline.syncAndReturnAll();
//        long end = System.currentTimeMillis();
//        pool.returnResource(one);
//        System.out.println("[email protected] SET: " + ((end - start)/1000.0) + " seconds");
//        pool.destroy();

/**************************其他**************************/    

        /**
         * 清空所有
         */
//        js.flushAll();

        /**
         * 销毁链接
         */
//        js.disconnect();

}

开始贴代码了,springMVC整合jedis

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>SpringMVC-Redis</display-name>

  <!-- 引入 spring -->
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:/applicationContext*.xml</param-value>
  </context-param>

  <!-- 引入 springMVC -->
  <servlet>
      <servlet-name>springMVC</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath*:/spring-servlet-config.xml</param-value>
      </init-param>
  </servlet>
  <servlet-mapping>
      <servlet-name>springMVC</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!-- 编码 UTF-8 -->
  <filter>
      <filter-name>SpringMVC-Redis-Encoding</filter-name>
      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
      <init-param>
          <param-name>encoding</param-name>
          <param-value>UTF-8</param-value>
      </init-param>
      <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>SpringMVC-Redis-Encoding</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>

</web-app>

index.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery/jquery-1.8.0.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>index 2</title>
</head>
<body>
    <div><font color="red" size="10px">${returnMsg}</font></div>
    <form action="${pageContext.request.contextPath }/TestRequest/test" method="post" name="loginForm" id="loginForm">
        <div>
            用户名:<input class="username" type="text" id="username" name="username"  value=‘‘/>
        </div>
        <div >
            密码:<input class="password" type="password" id="password" name="password" value=""/>
        </div>
        <div><input type="button" value="submit" onclick="login()" /></div>
    </form>
<script type="text/javascript">

    function login(){
        var username = $("#username").val();
        var password = $("#password").val();
        $("#loginForm").submit();
    }

    document.onkeydown=function(event){
        e = event ? event :(window.event ? window.event : null);
        if(e.keyCode==13){
            login();
        }
    } 

</script>
</body>
</html>

spring-servlet-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">  

    <!-- 使用@Controllers前配置 -->
    <mvc:annotation-driven />            

    <!-- 容器加载时 自动扫描所有注解 -->
    <context:component-scan base-package="com.test" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" />
    </context:component-scan>     

     <!-- 配置静态资源  -->
    <mvc:resources mapping="/js/**" location="/js/" />
    <mvc:resources mapping="/image/**" location="/image/" />
    <mvc:resources mapping="/css/**" location="/css/" />     

      <!-- 使用jsp作为视图 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass">
            <value>org.springframework.web.servlet.view.JstlView</value>
        </property>
        <!-- 目标路径返回到pages下 使用jsp作为视图 -->
        <property name="prefix" value="/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>    

    <!-- 异常处理 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>
            </props>
        </property>
    </bean>    

</beans>

先把这些贴上来是因为这些文件内容都和上篇博文”springMVC+memcached “的一模一样

applicationContext.xml

利用spring的构造注入,把集群参数传入RedisInitBean中,并且在项目启动的时候加载RedisInitBean的有参构造方法

<?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"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

    <bean id="RedisInitBean" class="com.test.test.RedisInitBean" >
        <!-- IP:Port -->
        <constructor-arg index="0" type="List">
            <list>
                <value>127.0.0.1:6379</value>
                <value>192.168.3.27:6380</value>
            </list>
        </constructor-arg>
        <!-- maxWaitMillis -->
        <constructor-arg index="1" type="long">
            <value>1000</value>
        </constructor-arg>
        <!-- MaxIdle -->
        <constructor-arg index="2" type="int">
            <value>200</value>
        </constructor-arg>
        <!-- testOnBorrow -->
        <constructor-arg index="3" type="Boolean">
            <value>true</value>
        </constructor-arg>
    </bean>

</beans>

RedisInitBean.java

这里面要说一下,使用的是 分布式连接池 异步调用!

package com.test.test;

import java.util.Arrays;
import java.util.List;

import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

public class RedisInitBean {

    private List Host;
    private long maxWaitMillis;
    private int MaxIdle;
    private Boolean testOnBorrow;
    private static List<JedisShardInfo> shards ;
    private static ShardedJedisPool pool;
    private static ShardedJedis jedis;

    public RedisInitBean(List host, long maxWaitMillis, int maxIdle,
            Boolean testOnBorrow) {
        super();
        Host = host;
        this.maxWaitMillis = maxWaitMillis;
        MaxIdle = maxIdle;
        this.testOnBorrow = testOnBorrow;
        if(host.size()!=0){
            for (int i = 0; i < host.size(); i++) {
                String h[] = ((String) host.get(i)).split(":");
                shards = Arrays.asList(new JedisShardInfo(h[0].trim(),Integer.parseInt(h[1].trim())));
                System.out.println(shards);
            }
        }else{
            System.out.println("请检查Redis配置,host项为必填项!格式[IP:PORT]");
        }

        pool = new ShardedJedisPool(new JedisPoolConfig(), shards);
        jedis = pool.getResource();
    }

    public synchronized ShardedJedis getSingletonInstance(){
        return jedis;
    }

    public synchronized static void returnResource(){
        pool.returnResource(jedis);
    }

    public synchronized static void destroy(){
        pool.destroy();
    }

}

TestRequest.java

刚才我们写的index.jsp中,提交了表单后浏览器会发起请求,spring拦截请求后会找到注解匹配的类中的方法,TestRequest就是了。

package com.test.web;

import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPipeline;

import com.test.test.RedisInitBean;

@Controller
@RequestMapping("/TestRequest")
public class TestRequest {

    @Autowired
    private RedisInitBean rib;

    @RequestMapping("/test")
    public ModelAndView test(@RequestParam(value = "username") final String userid,
            @RequestParam(value = "password") final String passwd, HttpSession session){

        ModelAndView m = new ModelAndView();
        m.setViewName("../index");
        ShardedJedis jedis = rib.getSingletonInstance();
        ShardedJedisPipeline pipeline = jedis.pipelined();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 99999; i++) {
            pipeline.set("zhenbn" + i, "n" + i);
        }
        List<Object> results = pipeline.syncAndReturnAll();
        long end = System.currentTimeMillis();
        rib.returnResource();
        rib.destroy();
        System.out.println("分布式连接池异步调用耗时: " + ((end - start)/1000.0) + " 秒");
        try {
            Thread.sleep(5000);//睡5秒,然后打印jedis返回的结果
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("返回结果:"+results);
        m.addObject("returnMsg","么么哒!");
        return m;
    }

}

存完之后,我们可以取一下试试,看看到底有没有存进去。

看,取到了吧~

使用jedis的时候要注意配合commons-pool2.jar使用,否则会报错的。

原因是 JedisPoolConfig extends GenericObjectPoolConfig,

而GenericObjectPoolConfig则是:

BaseObjectPoolConfig则是:

jar包下载:http://pan.baidu.com/s/1jGBVJds

时间: 2024-11-12 18:44:51

springMVC整合jedis+redis,以注解形式使用的相关文章

springMVC整合jedis+redis

http://www.cnblogs.com/zhengbn/p/4140549.html 前两天写过 springMVC+memcached 的整合,我从这个基础上改造一下,把redis和springmvc整合到一起. 和memcached一样,redis也有java专用的客户端,官网推荐使用的是:jedis. 看了一部分资料,大家推荐使用 spring-data-redis (spring在jedis的基础上又包装了一层),但是实际中感觉写起来有点麻烦,不如原生态的jedis好用. 所以我利

springmvc整合redis架构搭建实例

新换环境,又有新东西可以学习了,哈皮! 抽空学习之余看了一下redis,个人对Springmvc的爱是忠贞不渝,所以整理了一下Springmvc整合redis的环境搭建.分享学习. 第一步: 创建maven项目: 实例pom.xml内容如下 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns

spring和springMVC整合注解版helloworld

整合的之前需要从官网上下载spring完整的jar包,我下载的是spring-framework-3.2.2.RELEASE.整合步骤如下: 1.在eclipse中新建一个web项目,将下载的spring的jar包拷入lib目录下,但是spring启动的时候依赖一个commons-logging-1.1.jar的jar包,你需要额外的下载. 2.编写web.xml,配置spring的分发器和spring配置文件的位置.具体内容如下: <servlet> <servlet-name>

安全框架 - Shiro与springMVC整合的注解以及JSP标签

Shiro想必大家都知道了,之前的文章我也有提过,是目前使用率要比spring security都要多的一个权限框架,本身spring自己都在用shiro,之前的文章有兴趣可以去扒一下 最近正好用到shiro,简单聊聊几个小tips吧 <!-- 对静态资源设置匿名访问,即可以未登录状态下访问 --> /images/** = anon /js/** = anon /styles/** = anon /css/** = anon /page/getOrders.action = perms[or

Spring学习(六)spring整合注解形式的hibernate

上篇博客中谈到spring中如何整合普通形式的hibernate,这次我们来总结下如何整合注解形式的hibernate. 我们知道在普通hibernate中,表与实体的映射关系是写在映射关系文件当中的,一个实体类对应一个映射关系配置文件.而在注解形式中是没有这个映射关系文件的,关系直接在实体类中通过注解的方式展现,所以写法上略有些不同. 下面我们通过一个例子来看看他们的区别.还是使用上篇博客的例子,先去掉这个hibernate反向生成的City.hbm.xml文件. Dao层里面是不需要修改的,

ssm+redis整合(通过aop自定义注解方式)

此方案借助aop自定义注解来创建redis缓存机制. 1.创建自定义注解类 package com.tp.soft.common.util; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementTyp

玩转 SSH(六):SpringMVC + MyBatis 架构搭建(注解版)

一.创建 SSMVCAnnoDemo 项目 点击菜单,选择“File -> New Project” 创建新项目.选择使用 archetype 中的 maven-webapp 模版创建. 输入对应的项目坐标GroupId 和 ArtifactId 之后在项目名称中填入项目名称,这里我填的 ProjectName 和上文的 ArtifactId 相同,都是 SSMVCAnnoDemo. 点击确定后,等待 Maven 帮我们构建好项目的目录结构.当控制台显示 BUILD SUCCESS 就表示初始化

springMVC整合xStream

一. 简单介绍: xStream能够轻易的将Java对象转换成xml.JSON.本篇博客将使用springMVC整合利用xStream转换xml. 关于xStream使用的博文:http://blog.csdn.net/zdp072/article/details/39054197 二. 实例: 1. 代码结构图: 2. 实体类: (1)Account public class Account { private int id; private String name; private Stri

SSM框架中以注解形式实现事务管理

上一篇博文<SSM三大框架整合详细教程>详细说了如何整合Spring.SpringMVC和MyBatis这三大框架.但是没有说到如何配置mybatis的事务管理,实现开发中,事务是必不可少的.本篇作为对上一篇的补充,说明在SSM框架中如何使用注解的形式进行事务管理. 什么是事务? 在编写业务的过程中,会需要进行事务处理,当需要执行多条插入语句时,如果前几条成功,而最后一条失败,那么我们需要回滚数据库操作,保持数据的一致性和完整性,此时,就需要利用DB的事务处理.事务是恢复和并发控制的基本单位.