springboot集成mybatis/分页/transaction

pom.xml

<dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.1.1</version>
           </dependency>
           <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
           </dependency>
           <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <!-- <version>4.1.6</version> -->
                <version>5.1.1</version>
           </dependency>
           <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

application.yml

spring:
  application:
    name: spring-cloud-api-mybatis
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.jdbc.Driver
    url:  jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
    username: 
    password: 
mybatis:
  config-locations: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml
  type-aliases-package: com.daimeng

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config  3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
     <typeAliases>
           <typeAlias alias="Integer" type="java.lang.Integer" />
           <typeAlias alias="Long" type="java.lang.Long" />
           <typeAlias alias="HashMap" type="java.util.HashMap" />
           <typeAlias alias="LinkedHashMap"  type="java.util.LinkedHashMap" />
           <typeAlias alias="ArrayList"  type="java.util.ArrayList" />
           <typeAlias alias="LinkedList"  type="java.util.LinkedList" />
     </typeAliases>
</configuration>

TransactionAdviceConfig.java

package com.daimeng.api.interceptor;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;
/**
* 通过AOP切面设置全局事务,拦截service包下面所有方法
* AOP术语:通知(Advice)、连接点(Joinpoint)、切入点(Pointcut)、切面(Aspect)、目标(Target)、代理(Proxy)、织入(Weaving)
* @author daimeng
*
*/
@Aspect
@Configuration
public class TransactionAdviceConfig {
    
    /*定义切点变量:拦截com包下所有类的所有方法,返回值类型任意的方法*/
    //private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.***.service.*.*(..))";
    //..表示包含子路劲
    private static final String AOP_POINTCUT_EXPRESSION = "execution (* com..service..*+.*(..))";
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    /**
     * springBoot事务配置
     * @return
     */
    @Bean
    public TransactionInterceptor txAdvice() {
        DefaultTransactionAttribute txAttr_REQUIRED = new DefaultTransactionAttribute();
        //如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务
        txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        //只读事物、不做更新删除等
        DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
        txAttr_REQUIRED_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        txAttr_REQUIRED_READONLY.setReadOnly(true);
        
        //事务管理规则,声明具备事务管理的方法名
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        source.addTransactionalMethod("add*", txAttr_REQUIRED);
        source.addTransactionalMethod("save*", txAttr_REQUIRED);
        source.addTransactionalMethod("delete*", txAttr_REQUIRED);
        source.addTransactionalMethod("update*", txAttr_REQUIRED);
        source.addTransactionalMethod("exec*", txAttr_REQUIRED);
        source.addTransactionalMethod("set*", txAttr_REQUIRED);
        source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);
        return new TransactionInterceptor(transactionManager, source);
    }
    /**
     * 利用AspectJExpressionPointcut设置切面=切点+通知(写成内部bean的方式)
     * @return
     */
    @Bean
    public Advisor txAdviceAdvisor() {
        /* 声明切点的面
         * 切面(Aspect):切面就是通知和切入点的结合。通知和切入点共同定义了关于切面的全部内容——它的功能、在何时和何地完成其功能。
         * */
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        /*声明和设置需要拦截的方法,用切点语言描写*/
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        /*设置切面=切点pointcut+通知TxAdvice*/
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
}

Application.java

package com.daimeng.api;
import java.util.Properties;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInterceptor;
@SpringBootApplication
@EnableDiscoveryClient
//声明成mybatis Dao层的Bean,也可以在DAO/Mapper类上加@Mapper注解声明
@MapperScan("com.daimeng.**.mapper")
public class ApiServerApplication {
    @Value("${datasource.dialect}")
    private String dialect;
    @Value("${pagehelper.offsetAsPageNum}")
    private String offsetAsPageNum;
    @Value("${pagehelper.rowBoundsWithCount}")
    private String rowBoundsWithCount;
    @Value("${pagehelper.reasonable}")
    private String reasonable;
    
    public static void main(String[] args) {
        SpringApplication.run(ApiServerApplication.class, args);
    }
    /**
     * mysql 分页插件
     * @return
     */
    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("offsetAsPageNum", offsetAsPageNum);
        properties.setProperty("rowBoundsWithCount", rowBoundsWithCount);
        properties.setProperty("reasonable", reasonable);
        System.out.println("######################pageHelper#########################");
        System.out.println(dialect);
        System.out.println(offsetAsPageNum);
        System.out.println(rowBoundsWithCount);
        System.out.println(reasonable);
        System.out.println("######################pageHelper#########################");
        properties.setProperty("dialect", dialect); // 配置mysql数据库的方言
        pageHelper.setProperties(properties);
        return pageHelper;
    }
    /**
     * mysql 分页插件
     * @return
     */
    @Bean
    public PageInterceptor pageInterceptor() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        System.out.println("######################pageInterceptor#########################");
        System.out.println(dialect);
        System.out.println("######################pageInterceptor#########################");
        properties.setProperty("helperDialect", dialect); // 配置mysql数据库的方言
        pageInterceptor.setProperties(properties);
        return pageInterceptor;
    }
}

UserMapper.java

package com.daimeng.api.user.mapper;
import java.util.ArrayList;
import com.daimeng.api.user.entity.UserEntity;
public interface UserMapper {
    public ArrayList<UserEntity> getAll();
    public ArrayList<UserEntity> getUserByLoginName(UserEntity user);
    public void saveUser(UserEntity user);
    public Long countUserByLoginName(String loginName);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.daimeng.api.user.mapper.UserMapper" >
    <select id="getAll"  resultType="com.daimeng.api.user.entity.UserEntity"  >
       SELECT id as id,
                 login_name as loginName,
                 password as password,
                 realname as realName,
                 email as email,
                 phone as phone
        FROM sys_user
        <if test="loginName != null and loginName != ''">
           and login_name = #{loginName}
        </if>
        order by id asc
    </select>
    <select id="getUserByLoginName"  resultType="com.daimeng.api.user.entity.UserEntity"  >
       SELECT id as id,
                 login_name as loginName,
                 password as password,
                 realname as realName,
                 email as email,
                 phone as phone
        FROM sys_user
        where 1=1
        <if test="loginName != null and loginName != ''">
           and login_name = #{loginName}
        </if>
        order by id asc
    </select>
    
    <insert id="saveUser"  >
       insert into sys_user(login_name,password)  values(#{loginName},#{password})
    </insert>
    <select id="countUserByLoginName" resultType="java.lang.Long"   >
       SELECT count(id)
        FROM sys_user
        where 1=1
           and login_name = #{0}
    </select>
</mapper>

UserService.java

package com.daimeng.api.user.service;
import java.util.ArrayList;
import com.daimeng.api.user.entity.UserEntity;
import com.github.pagehelper.PageInfo;
public interface UserService {
    public ArrayList<UserEntity> getAll();
    public PageInfo<UserEntity> getPage(Integer pageNum);
    public ArrayList<UserEntity> getUserByLoginName(UserEntity user);
    public void saveUser(UserEntity user);
}

UserServiceImpl.java

package com.daimeng.api.user.service.impl;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.daimeng.api.user.entity.UserEntity;
import com.daimeng.api.user.mapper.UserMapper;
import com.daimeng.api.user.service.UserService;
import com.daimeng.api.utils.Constants;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public ArrayList<UserEntity> getAll() {
        try {
            ArrayList<UserEntity> list = userMapper.getAll();
            return list;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    @Override
    public ArrayList<UserEntity> getUserByLoginName(UserEntity user) {
        try {
            ArrayList<UserEntity> list = userMapper.getUserByLoginName(user);
            return list;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * springboot实现事务只需要    在头上加上@Transactional注解
     * @Transactional 默认只捕获RuntimeException.class
     * 对Exception异常得需要 @Transactional(rollbackFor = {Exception.class}) 捕获回滚
     * 或者使用全局AOP配置 TransactionAdviceConfig
     */
    //@Transactional
    @Override
    public void saveUser(UserEntity user) {
        userMapper.saveUser(user);
        if(user.getPassword() == null || "".equals(user.getPassword()) ||
                user.getLoginName() == null || "".equals(user.getLoginName())){
            throw new RuntimeException("发生异常,用户名或密码为空");
        }
        Long count = userMapper.countUserByLoginName(user.getLoginName());
        if(count != null && count > 1){
            throw new RuntimeException("发生异常,用户名已存在");
        }
    }
    @Override
    public PageInfo<UserEntity> getPage(Integer pageNum) {
        //设置分页信息,分别是当前页数和每页显示的总记录数【记住:必须在mapper/dao接口中的方法执行之前设置该分页信息】
        PageHelper.startPage(pageNum, Constants.PAGE_SIZE);
        ArrayList<UserEntity> list = userMapper.getAll();
        PageInfo<UserEntity> pageInfo = new PageInfo<UserEntity>(list);
        //System.out.println(pageInfo.getTotal());
        return pageInfo;
    }
}

UserController.java

package com.daimeng.api.user.action;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.daimeng.api.user.entity.UserEntity;
import com.daimeng.api.user.service.UserService;
import com.github.pagehelper.PageInfo;
@RestController
@RequestMapping("/user")
public class UseController {
    @Autowired
    private UserService userService;
    
    @RequestMapping("/getList")
    public List<UserEntity> getUsers() {
        ArrayList<UserEntity> users = userService.getAll();
        return users;
    }
    
    @RequestMapping("/getPage/{pageNum}")
    public PageInfo<UserEntity> getUserPage(@PathVariable("pageNum") Integer pageNum) {
        PageInfo<UserEntity> users = userService.getPage(pageNum);
        return users;
    }
    
    @RequestMapping("/get/{loginName}")
    public List<UserEntity> getUserByLoginName(@PathVariable("loginName") String loginName) {
        UserEntity user = new UserEntity();
        user.setLoginName(loginName);
        ArrayList<UserEntity> users = userService.getUserByLoginName(user);
        return users;
    }
    
    @RequestMapping("/save")
    public String saveUser(String loginName,String password) {
        UserEntity user = new UserEntity();
        user.setLoginName(loginName);
        user.setPassword(password);
        try {
            userService.saveUser(user);
            return "新增用户成功";
        } catch (Exception e) {
            return e.getMessage();
        }
        
    }
    
}


{context}