spring整合mybatis-plus

鲍高扬
2023-12-01

spring整合mybatis-plus

1.添加依赖pom.xml

提示:集成mybatis-plus要把mybatis坐标和mybatis-spring坐标去掉,避免冲突

<?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.woniu</groupId>
   <artifactId>spring-mybatis-plus</artifactId>
   <version>1.0-SNAPSHOT</version>

   <properties>
       <maven.compiler.source>8</maven.compiler.source>
       <maven.compiler.target>8</maven.compiler.target>
   </properties>

   <dependencies>
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>8.0.23</version>
       </dependency>

       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid</artifactId>
           <version>1.2.5</version>
       </dependency>

       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.13</version>
           <scope>test</scope>
       </dependency>

       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>1.18.22</version>
       </dependency>

       <dependency>
           <groupId>ch.qos.logback</groupId>
           <artifactId>logback-classic</artifactId>
           <version>1.2.3</version>
       </dependency>

       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>5.2.9.RELEASE</version>
       </dependency>

       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-test</artifactId>
           <version>5.2.9.RELEASE</version>
       </dependency>
       
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-jdbc</artifactId>
           <version>5.2.9.RELEASE</version>
       </dependency>

       <!--mybatisPlus 自动生成器-->
       <dependency>
           <groupId>com.baomidou</groupId>
           <artifactId>mybatis-plus-generator</artifactId>
           <version>3.4.0</version>
       </dependency>

       <!--mybatisPlus默认模板-->
       <dependency>
           <groupId>org.apache.velocity</groupId>
           <artifactId>velocity-engine-core</artifactId>
           <version>2.2</version>
       </dependency>

   </dependencies>

   <build>
       <!--配置maven编译插件-->
       <plugins>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <version>3.5.1</version>
               <configuration>
                   <source>1.8</source>  <!-- 源代码使用的开发版本 -->
                   <target>1.8</target>  <!-- 需要生成的目标class文件的编译版本 -->
                   <encoding>UTF-8</encoding>
               </configuration>
           </plugin>
       </plugins>
   </build>
</project>

2.创建代码生成工具类

MybatisPlusCodeUtils.java,运行后将帮助我们自动生成代码

package com.woniu.util;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

/**
* MyBatisPlusCode代码生成工具类
*/
public class MyBatisPlusCodeUtil {
   private static final String XML_PATH="/resources/mapper/";
   private static final String ENTITY_IGNORE_PREFIX="smbms_";

   /**
    * 启动方法
    * @param args
    */
   public static void main(String[] args) {
       try {
           generator("gp",//作者
                   "jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai",
                   "com.mysql.cj.jdbc.Driver",//数据库驱动
                   "root",//数据库帐号
                   "root",//数据库密码
                   "com.woniu",//项目最大的包名
                   "spring-mybatis-plus",//项目名或项目模块名
                   "smbms_user,smbms_role");//要操作的表名,多个表名用逗号隔开
           System.out.println("mybaits代码生成成功");
       }catch (Exception e){
           e.printStackTrace();
       }
   }

   /**
    * Mybatis一键生成entity,mapper,mapper.xml,service,serviceImpl,controller
    * @param author            开发人员
    * @param url               驱动连接的URL
    * @param driverName        驱动名称
    * @param username          数据库连接用户名
    * @param password          数据库连接密码
    * @param parentPackage     父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
    * @param projectModule     项目名
    * @param tableName         表名,多个表名逗号隔开
    */
   public static void generator(String author,
                                String url,
                                String driverName,
                                String username,
                                String password,
                                String parentPackage,
                                String projectModule,
                                String tableName) {
       AutoGenerator mpg = new AutoGenerator();
       mpg.setGlobalConfig(globalConfig(author,projectModule));//全局配置
       mpg.setDataSource(dataSourceConfig(url,driverName,username,password));//数据源配置
       mpg.setPackageInfo(packageConfig(parentPackage));//包配置
       mpg.setStrategy(strategyConfig(tableName));//策略配置
       mpg.setTemplate(templateConfig());//模板配置
       mpg.execute();
   }

   /**
    * 全局配置
    * @param author            开发人员
    * @param projectModule     项目模块名
    * @return                  GlobalConfig
    */
   private static GlobalConfig globalConfig (String author, String projectModule) {
       String projectPath = System.getProperty("user.dir");
       GlobalConfig globalConfig = new GlobalConfig();
       // 文件输出目录
       //如果要在项目中生成用这个
      // globalConfig.setOutputDir(projectPath + "\\src\\main\\java");
       //如果要在模块中生成用这个
       globalConfig.setOutputDir(projectPath + "\\" + projectModule + "\\src\\main\\java");
       // 添加作者信息
       globalConfig.setAuthor(author);
       //设置时间类型为Date
       globalConfig.setDateType(DateType.TIME_PACK);
       // 生成文件后不默认打开
       globalConfig.setOpen(false);
       // 自定义service生成的名字,用于删除自动生成的I前缀
       globalConfig.setServiceName("%sService");
       // 自定义dao生成的名字,如果不指定默认为%sMapper
       //globalConfig.setMapperName("%sDao");
       return globalConfig;
   }

   /**
    * 数据源设置
    * @param url           驱动连接的URL
    * @param driverName    驱动名称
    * @param username      数据库连接用户名
    * @param password      数据库连接密码
    * @return              DataSourceConfig
    */
   private static DataSourceConfig dataSourceConfig (String url,
                                                     String driverName,
                                                     String username,
                                                     String password) {
       DataSourceConfig dataSourceConfig = new DataSourceConfig();
       dataSourceConfig.setUrl(url);
       dataSourceConfig.setDriverName(driverName);
       dataSourceConfig.setUsername(username);
       dataSourceConfig.setPassword(password);
       return dataSourceConfig;
   }

   /**
    * 包配置
    * @param parentPackage       父包名,最大的包名
    * @return                  PackageConfig
    */
   private static PackageConfig packageConfig(String parentPackage) {
       // 包配置
       PackageConfig packageConfig = new PackageConfig();
       // 包名
       packageConfig.setParent(parentPackage);
       //各个包目录起名
       packageConfig.setEntity("entity");
       packageConfig.setMapper("mapper");
       packageConfig.setXml("mapper");
       packageConfig.setService("service");
       return packageConfig;
   }

   /**
    * 策略配置
    * @param tableName     数据库表名称,多个用英文逗号隔开
    * @return              StrategyConfig
    */
   private static StrategyConfig strategyConfig (String tableName) {
       // 策略配置
       StrategyConfig strategyConfig = new StrategyConfig();
       // 表名驼峰命名
       strategyConfig.setNaming(NamingStrategy.underline_to_camel);
       // 字段驼峰命名
       strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
       // 设置去除表前缀
       strategyConfig.setTablePrefix(ENTITY_IGNORE_PREFIX);
       // 设置实体类的lombok(此处看个人使用,如果不使用lombok,那么在生成之后再去添加构造方法等等)
       strategyConfig.setEntityLombokModel(true);
       //strategyConfig.setRestControllerStyle(true);
       // scanner("表名,多个英文逗号分割").split(",")
       strategyConfig.setInclude((tableName).split(","));
       // 驼峰生成方法
       strategyConfig.setControllerMappingHyphenStyle(true);
       return strategyConfig;
   }

   /**
    * 模板配置项
    * @return  TemplateConfig
    */
   private static TemplateConfig templateConfig () {
       TemplateConfig templateConfig = new TemplateConfig();
       templateConfig.setXml(ConstVal.TEMPLATE_XML);
       //不生成mapper.xml文件
       templateConfig.setXml(null);
       //不生成service
       //templateConfig.setService(null);
       //不生成service实现类
       //templateConfig.setServiceImpl(null);
       //不生成controller类
       templateConfig.setController(null);
       return templateConfig;
   }
}

生成的实体类:

@Data
@EqualsAndHashCode(callSuper = false)
@TableName("smbms_role")
public class Role implements Serializable {

   private static final long serialVersionUID = 1L;

   /**
    * 主键ID
    */
   @TableId(value = "id", type = IdType.AUTO)
   private Integer id;

   /**
    * 角色编码
    */
   @TableField("roleCode")
   private String roleCode;

   /**
    * 角色名称
    */
   @TableField("roleName")
   private String roleName;
   ...
}

生成 Mapper接口

public interface RoleMapper extends BaseMapper<Role> {

}

因为mapper接口继承了mybatis-plus 的接口,因此我们的接口中自然 “天生就有” 若干方法

3.spring整合mybatisPlus

mybatis-plus和spring整合步骤同spring整合mybatis,唯一的不同就是将Spring的SqlSessionFactoryBean,改为mybatis plus的MybatisSqlSessionFactoryBean对象

JdbcConfig.java

package com.woniu.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@PropertySource("db.properties")
public class JdbcConfig {
   @Value("${jdbc.url}")
   private String url;

   @Value("${jdbc.driver}")
   private String driverClassName;

   @Value("${jdbc.user}")
   private String username;

   @Value("${jdbc.pass}")
   private String password;


   //@Bean注解 调用此方法,将返回值对象以方法名为id存入spring容器中
   @Bean("dataSource")
   public DataSource createDataSource(){
       DruidDataSource dataSource = new DruidDataSource();
       dataSource.setUrl(url);
       dataSource.setDriverClassName(driverClassName);
       dataSource.setUsername(username);
       dataSource.setPassword(password);
       dataSource.setInitialSize(4);
       dataSource.setMaxActive(100);
       dataSource.setMinIdle(2);
       return dataSource;
   }
}

完整的SpringConfiguration配置:

package com.woniu.config;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import javax.sql.DataSource;
import java.io.IOException;

/**
* Spring配置类
*/
@Configuration
@ComponentScan(basePackages = {"com.woniu"})  //扫描有spring注解的类所在的包
@Import(JdbcConfig.class)
public class SpringConfiguration {
   @Bean("sqlSessionFactoryBean")
   public MybatisSqlSessionFactoryBean createMybatisSqlSessionFactoryBean(DataSource dataSource) throws IOException {
       MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
       //向sqlSessionfactoryBean注入数据源
       factoryBean.setDataSource(dataSource);
       //设置类型别名
       factoryBean.setTypeAliasesPackage("com.woniu.entity");
       //将mybatis配置文件交给sqlSessionFactoryBean管理
       //factoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
       //设置sqlMapper XML映射文件的路径
       ResourcePatternResolver loader = new PathMatchingResourcePatternResolver();
       factoryBean.setMapperLocations(
               loader.getResources("classpath:com/woniu/mapper/*.xml"));
       return factoryBean;
   }

   //用于生成Mapper接口代理子类对象,并存入spring容器中
   @Bean
   public MapperScannerConfigurer getMapperScannerConfigurer() {
       MapperScannerConfigurer configurer = new MapperScannerConfigurer();
       configurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
       configurer.setBasePackage("com.woniu.mapper");
       return configurer;
   }
}

4.MybatisPlus CRUD操作

通用Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行 remove 删除``list 查询集合 page 分页 前缀命名方式区分 Mapper

4-1 查询操作

a.查询所有

selectList()方法需要传一个条件构造器,如果要查询所有,设置null即可

public interface UserService extends IService<User> {
   List<User> findUserList();
}


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

   @Autowired
   private UserMapper userMapper;

   //查询所有用户列表
   public List<User> findUserList() {
       return userMapper.selectList(null);
   }
}

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= SpringConfiguration.class)
public class UserServiceTest {

   @Autowired
   private UserService userService;

   @Test
   public void testFindUserList(){
      // List<User> userList = userService.list(); //IService自带
       List<User> userList = userService.findUserList(); //自定义业务方法
       for (User user : userList) {
           System.out.println(user);
       }
   }
}
b.通过主键查询

测试类:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;


    //根据主键查询
    public User selectById(Integer id) {
        return userMapper.selectById(id);
    }
}

@Test
public void testGetById(){
    User user = userService.getById(1);  //IService自带
    User user = userService.selectById(1);//自定义业务方法
    System.out.println(user);
}
c.通过多个主键id批量查询
@Test
public void testSelectByIds(){
    List<Integer> ids = new ArrayList<>();
    ids.add(1);
    ids.add(2);
    ids.add(3);

    List<User> userList = userService.listByIds(ids);
    for (User user : userList) {
        System.out.println(user);
    }
}

4-2 条件查询

要想为sql语句添加where条件,需要使用mybatis plus的条件构造器对象Wrapper,该对象中提供了对sql条件操作的各种方法:

官网:https://baomidou.com/pages/10c804/#alleq

示例:查询性别为‘男’,根据生日降序排列

@Test
    public void testSelectUserByCondition(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("user_name","熊");
        queryWrapper.or().eq("gender",1);
        queryWrapper.orderByDesc("birthday");
        List<User> userList = userService.list(queryWrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }
SELECT id,userCode,user_name,userPassword,gender,birthday,phone,address,roleid,createdBy,creationDate,modifyBy,modifyDate,IDPICPATH FROM smbms_user WHERE (user_name LIKE ? OR gender = ?) ORDER BY birthday DESC

4-3 分页查询

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

  • 在spring的配置类中添加mybatis plus的分页插件拦截器

@Bean("sqlSessionFactoryBean")
public MybatisSqlSessionFactoryBean createMybatisSqlSessionFactoryBean(DataSource dataSource) throws IOException {
    MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
    //向sqlSessionfactoryBean注入数据源
    factoryBean.setDataSource(dataSource);
    //设置类型别名
    factoryBean.setTypeAliasesPackage("com.woniu.entity");
    //将mybatis配置文件交给sqlSessionFactoryBean管理
    //factoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
    //设置sqlMapper XML映射文件的路径
    ResourcePatternResolver loader = new PathMatchingResourcePatternResolver();
    factoryBean.setMapperLocations(
        loader.getResources("classpath:com/woniu/mapper/*.xml"));

    //配置mybatis plus分页插件
    MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
    //设置分页拦截器,指定 mysql数据库类型
    mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    factoryBean.setPlugins(mybatisPlusInterceptor);
    return factoryBean;
}
  • 业务层编写分页代码

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

        @Autowired
        private UserMapper userMapper;
    
        //获取分页数据
        public IPage<User> getPageInfo(int pageNum, int pageSize) {
            IPage<User> page = new Page<>(pageNum,pageSize);
            //参数1为分页参数,参数2为分页查询条件
            IPage<User> pageInfo  = userMapper.selectPage(page,null);
            return pageInfo;
        }
}

测试业务类,获取分页数据

 @Test
public void testGetByPage(){
    IPage<User> userPage = new Page<>(1,3);
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //第二个参数为查询条件
    IPage<User> page = userService.page(userPage,queryWrapper); //使用IService中的方法
    //IPage<User> page = userService.getPageInfo(1,3);
    for (User user : page.getRecords()) {
        System.out.println(user);
    }
    System.out.println("page.getPages():"+page.getPages());
    System.out.println("page.getCurrent():"+page.getCurrent());
    System.out.println("page.getSize():"+page.getSize());
    System.out.println("page.getTotal():"+page.getTotal());
}

4-4 逻辑条件组合

逻辑条件的组合大体分为 2 种:

  • 单纯的 ...与...与... / ...或...或...

  • 与或 混用,由于 的优先级更高,因此可以改造成 (... and ...) or (... and ...) or ... 这样的统一形式。

a、与与和或或
  • ...与...与... 情况:

    如上例所示,QueryWrapper 的链式调用中,所表达的逻辑关系就是 and 的关系。

  • ...或...或... 情况:

    这种关系中,在 Wrapper 对象的链式调用中穿插调用 or() 方法即可。or() 方法前后的条件就是或的关系。

 /**
     * 条件查询
     * @return
     */
    public List<User> selectQuery(){
        QueryWrapper<User> queryWrapper=new QueryWrapper<User>()
                .like("username", "小") //根据姓名模糊查询
                .or()
                .eq("sex","男") //所有性别为男
                .orderByDesc("money"); //根据金额倒序
        return userMapper.selectList(queryWrapper);
    }
b、与或混用

与或混用的情况下,先要把你『心里』的 SQL 语句改造成通用形式:(... and ...) or (... and ...) or ...

4-5 删除操作

a、根据id删除
 @Test
public void testDeleteById(){
    boolean b = userService.removeById(46);
    System.out.println(b);

}
b、根据id批量删除
 @Test
public void testDeleteByIds(){
    List<Integer> ids = new ArrayList<>();
    ids.add(45);
    ids.add(43);
    userService.removeByIds(ids);
}
c、普通删除-根据条件删除
@Test
public void testDeleteByMap(){
    Map<String,Object> map = new HashMap<>();
    map.put("name","张三");
    map.put("gender",1);
    userService.removeByMap(map);
}
d、使用条件构造器删除
 @Test
public void testDeleteByWrapper(){
    Wrapper<User> wrapper = new QueryWrapper<User>()
        .eq("name","张三")
        .eq("gender",1);
    userService.remove(wrapper);
}

4-6 添加操作

 @Test
public void testAdd(){
    User user = new User();
    user.setUserCode("Jack");
    user.setUserName("杰克");
    user.setUserPassword("111");
    user.setGender(1);
    user.setBirthday(LocalDateTime.of(2000,11,15,13,50));
    user.setRoleid(1);
    userService.save(user);
}

4-7 更新操作

a、根据id更新
 @Test
public void testUpdate(){
    User user = new User();
    user.setId(47);
    user.setUserCode("Jenny");
    user.setUserName("詹妮");
    user.setUserPassword("999");
    user.setGender(2);
    user.setRoleid(2);
    userService.updateById(user);   
}
b、条件构造器作为条件更新

使用UpdateWrapper可以直接使用条件构造器封装设置的值,而无需new User对象进行设置

 @Test
public void testUpdateByWrapper(){
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.set("userCode","Jenny");
    updateWrapper.eq("id",47);
    updateWrapper.like("userCode","e");
    //User user = new User();
    //user.setGender(1);
    //user.setRoleid(1);
    //userService.update(user,updateWrapper);
    userService.update(updateWrapper);
}

5.Mybatis多表查询并分页

${ew.customSqlSegment} 不是必须写的。当你自定义方法还想用条件构造器Wrapper的时候,才需要这样写。可以使用mybatis原生的方式。

UserMapper.xml

<mapper namespace="com.woniu.mapper.UserMapper">
    <resultMap id="userResultMap" type="User">
        <id column="id" property="id" />
        <result column="userCode" property="userCode" />
        <result column="user_name" property="userName" />
        <result column="userPassword" property="userPassword" />
        <result column="gender" property="gender" />
        <result column="birthday" property="birthday" />
        <result column="roleid" property="roleid" />
        <association column="roleid" property="role" javaType="Role">
            <id column="roleid" property="id" />
            <result column="roleName" property="roleName" />
        </association>
    </resultMap>

    <!--mybatis-plus多表联合查询,带上${ew.customSqlSegment就可以实现查询-->
    <select id="queryUserAndRoleName" resultMap="userResultMap">
        select u.id,u.userCode,u.user_name,u.userPassword,u.gender,u.birthday,u.roleid,r.roleName
        from smbms_user u inner join smbms_role r on u.roleid=r.id
        <!--<where>-->
        <!--    <if test="user.userName != null and user.userName!=''">-->
        <!--        u.user_name like concat('%',#{user.userName},'%')-->
        <!--    </if>-->
        <!--</where>-->
      ${ew.customSqlSegment}
    </select>
</mapper>

UserMapper.java

public interface UserMapper extends BaseMapper<User> {

    IPage<User> queryUserAndRoleName(@Param("page") IPage<User> page,
                   @Param(Constants.WRAPPER) QueryWrapper<User> wrapper);
}

UserService.java

public interface UserService extends IService<User> {

    IPage<User> getUserAndRoleName(int pageNum, int pageSize, QueryWrapper<User> wrapper);
}

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    //分页条件查询
    public IPage<User> getUserAndRoleName(int pageNum, int pageSize, QueryWrapper<User> wrapper) {
        //开启分页
        Page<User> page = new Page<>(pageNum,pageSize);
        //将获取到的 page对象和前台传递的参数传递到自己写的sql查询方法
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like("user_name","熊");
        //注意返回值类型一定要是IPage<User>
        IPage<User> pageInfo = userMapper.queryUserAndRoleName(page, wrapper);
        return pageInfo;
}

UserServiceTest测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class UserServiceTest {
     @Test
    public void testGetUserAndRoleName() {
        User user = new User();
        user.setUserName("熊");
        IPage<User> page = userService.getUserAndRoleName(1, 3, user);
        List<User> records = page.getRecords();
        for (User record : records) {
            System.out.println(record);
        }
    }
}
 类似资料: