SpringBoot整合Mybatis注解动态SQL增删改查

  • Post author:
  • Post category:其他




零、知识介绍

动态SQL其实就是硬编码,不用xml方式,不用注解方式,可以更加灵活多变的使用java代码进行判断,业务逻辑处理生成一个SQL。

硬编码的执行速度比xml方式快,并且可以进行

debug

盘查错误,较全注解方式更加灵活,并且

可读性高

,缺点可能就是不流行,不能和xml接口一起使用,mybatis 3.4以上支持

多参数

,3.4以下,只能使用map传值。

因为是生成字符串SQL,依然存在SQL注入问题,所以必须使用

” username = #{username}”

,不能使用

” username = ” + username

方式



一、依赖准备

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!--SpingBoot集成junit测试的起步依赖-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!--mybatis起步依赖-->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.1.1</version>
		</dependency>

		<!-- MySQL连接驱动 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		
	</dependencies>



二、配置准备

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: 123
  mvc:
    view:
      suffix: .jsp
      prefix: /
  resources:
    static-locations: classpath:templates
mybatis:
  type-aliases-package: com.hikktn.domain
  mapper-locations: classpath:mapper/*Mapper.xml
  configuration:
    map-underscore-to-camel-case: true #开启自动驼峰命名规则(camel case)映射
    lazy-loading-enabled: true #开启延时加载开关
    aggressive-lazy-loading: false #将积极加载改为消极加载(即按需加载),默认值就是false
    lazy-load-trigger-methods: "" #阻挡不相干的操作触发,实现懒加载
    cache-enabled: true #打开全局缓存开关(二级环境),默认值就是true
logging:
  level:
   com.hikktn: debug
server:
  port: 8080
  servlet:
    context-path: /

log4j.properties

#---- global logging configuration
#---- level: FATAL,ERROR,WARN,INFO,DEBUG
#---- appender: console, file, mail
### set log levels ###
log4j.rootLogger=INFO,console
### 输出到控制台 ###
log4j.appender.stdout.encoding=UTF-8
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} %5p %c{1}:%L - %m%n
### 输出到日志文件 ###
#log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.file.File=${webapp.root}/WEB-INF/logs/platform.log
#log4j.appender.file.DatePattern=_yyyyMMdd'.log'
#log4j.appender.file.Append = true
#log4j.appender.file.Threshold = INFO
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss}  [ %t\:%r ] - [ %p ]  %m%n
### 打印SQL ###
#log4j.logger.com.ibatis=DEBUG
#log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
#log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
#log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
#log4j.logger.java.sql.ResultSet=DEBUG
#配置logger扫描的包路径  这样才会打印sql
log4j.logger.com.hikktn.mapper=DEBUG



三、数据准备

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'user', 'user');
INSERT INTO `user` VALUES (2, 'admin', 'admin');
INSERT INTO `user` VALUES (3, 'hikktn', 'hikktn0320');

SET FOREIGN_KEY_CHECKS = 1;



四、pojo准备

package com.hikktn.domain;

import java.io.Serializable;

public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;
    private String username;
    private String password;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}



五、mapper接口准备

@Mapper
@Repository
public interface UserMapper {
    /**
	 * 动态查询
	 *
	 * @param param
	 * @return
	 */
	@SelectProvider(type = UserDynaSqlProviderBuilder.class, method = "buildSelectUserWithParam")
	public List<User> selectUserInfoWithParam(Map<String, Object> param);

	/**
	 * 动态增加,并自动获取自增主键
	 *
	 * @param user
	 * @return
	 */
	@InsertProvider(type = UserDynaSqlProviderBuilder.class, method = "buildInsertUser")
	@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
	public int insertUser(User user);

	/**
	 * 动态根据id查询
	 *
	 * @param param
	 * @return
	 */
	 @Results({
			@Result(column = "id",property = "id"),
			@Result(column = "username",property = "username"),
			@Result(column = "password",property = "password")
	})
	@SelectProvider(type = UserDynaSqlProviderBuilder.class, method = "buildSelectUserWithParam")
	public User selectUserWithId(Map<String, Object> param);

	/**
	 * 动态修改
	 *
	 * @param user
	 */
	@UpdateProvider(type = UserDynaSqlProviderBuilder.class, method = "buildUpdateUser")
	public int updateUser(User user);

	/**
	 * 动态删除
	 *
	 * @param param
	 */
	@DeleteProvider(type = UserDynaSqlProviderBuilder.class, method = "buildDeleteUser")
	public int deleteUser(Map<String, Object> param);
}



六、动态SQL准备

public class UserDynaSqlProviderBuilder {

	/**
	 * 动态查询
	 *
	 * @param param
	 * @return
	 */
	public String buildSelectUserWithParam(Map<String, Object> param) {
		return new SQL() {
			{
				SELECT("*");
				FROM("user");
				if (param.get("id") != null) {
					WHERE(" id = #{id} ");
				}
				if (param.get("username") != null) {
					WHERE(" username = #{username} ");
				}
				if (param.get("password") != null) {
					WHERE(" password = #{password} ");
				}
			}
		}.toString();
	}

	/**
	 * 动态增加
	 *
	 * @param user
	 * @return
	 */
	public String buildInsertUser(User user) {
		return new SQL() {
			{
				INSERT_INTO("user");
				if (user.getUsername() != null) {
					VALUES("username", "#{username}");
				}
				if (user.getPassword() != null) {
					VALUES("password", "#{password}");
				}
			}
		}.toString();
	}

	/**
	 * 动态修改
	 *
	 * @param user
	 * @return
	 */
	public String buildUpdateUser(User user) {
		return new SQL() {
			{
				UPDATE("user");
				if (user.getUsername() != null) {
					SET("username = #{username}");
				}
				if (user.getPassword() != null) {
					SET("password = #{password}");
				}
				WHERE(" id = #{id} ");
			}
		}.toString();
	}

	/**
	 * 动态删除
	 * @param param
	 * @return
	 */
	public String buildDeleteUser(Map<String, Object> param) {
		return new SQL() {
			{
				DELETE_FROM("user");
				if (param.get("id") != null) {
					WHERE(" id = #{id} ");
				}
				if (param.get("username") != null) {
					WHERE(" username = #{username}");
				}
			}
		}.toString();
	}
}



七、测试用例准备

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootMybatisApplication.class)
public class MybatisTest {
	@Autowired
	private UserMapper userMapper;
	/**
	 * 动态查询
	 */
	@Test
	public void testSelectUser() {
		Map<String, Object> map = new HashMap<>();
		map.put("id", "1");
		map.put("username", "user");
		map.put("password", "user");
		List<User> users = userMapper.selectUserInfoWithParam(map);
		System.out.println(users);
	}

	/**
	 * 动态增加
	 */
	@Test
	public void testInsertUser() {
		User user = new User();
		user.setUsername("hikktn");
		user.setPassword("123456");
		int result = userMapper.insertUser(user);
		System.out.println("插入成功,返回结果:" + result);
	}

	/**
	 * 动态修改
	 */
	@Test
	public void testUpdateUser() {
		Map<String, Object> map = new HashMap<>();
		map.put("id", "3");
		User user = userMapper.selectUserWithId(map);
		user.setUsername("hikktn");
		user.setPassword("hikktn0320");
		userMapper.updateUser(user);
	}

	/**
	 * 动态删除
	 */
	@Test
	public void testDeleteUser() {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("username", "hikktn");
		userMapper.deleteUser(param);
	}
}



八、测试结果



查询结果

2021-08-13 11:56:46.283 DEBUG 400 --- [           main] c.h.m.U.selectUserInfoWithParam          : ==>  Preparing: SELECT * FROM user WHERE ( id = ? AND username = ? AND password = ? ) 
2021-08-13 11:56:46.299 DEBUG 400 --- [           main] c.h.m.U.selectUserInfoWithParam          : ==> Parameters: 1(String), user(String), user(String)
2021-08-13 11:56:46.322 DEBUG 400 --- [           main] c.h.m.U.selectUserInfoWithParam          : <==      Total: 1
[User{id=1, username='user', password='user'}]



增加结果

2021-08-13 12:12:03.155 DEBUG 796 --- [           main] com.hikktn.mapper.UserMapper.insertUser  : ==>  Preparing: INSERT INTO user (username, password) VALUES (?, ?) 
2021-08-13 12:12:03.175 DEBUG 796 --- [           main] com.hikktn.mapper.UserMapper.insertUser  : ==> Parameters: hikktn(String), 123456(String)
2021-08-13 12:12:03.181 DEBUG 796 --- [           main] com.hikktn.mapper.UserMapper.insertUser  : <==    Updates: 1
插入成功,返回结果:1



修改结果

2021-08-13 14:25:46.440 DEBUG 11172 --- [           main] c.h.mapper.UserMapper.selectUserWithId   : ==>  Preparing: SELECT * FROM user WHERE ( id = ? ) 
2021-08-13 14:25:46.458 DEBUG 11172 --- [           main] c.h.mapper.UserMapper.selectUserWithId   : ==> Parameters: 3(String)
2021-08-13 14:25:46.492 DEBUG 11172 --- [           main] c.h.mapper.UserMapper.selectUserWithId   : <==      Total: 1
2021-08-13 14:25:46.499 DEBUG 11172 --- [           main] com.hikktn.mapper.UserMapper.updateUser  : ==>  Preparing: UPDATE user SET username = ?, password = ? WHERE ( id = ? ) 
2021-08-13 14:25:46.499 DEBUG 11172 --- [           main] com.hikktn.mapper.UserMapper.updateUser  : ==> Parameters: hikktn(String), hikktn0320(String), 3(Long)
2021-08-13 14:25:46.516 DEBUG 11172 --- [           main] com.hikktn.mapper.UserMapper.updateUser  : <==    Updates: 1



删除结果

2021-08-13 14:26:49.140 DEBUG 14636 --- [           main] com.hikktn.mapper.UserMapper.deleteUser  : ==>  Preparing: DELETE FROM user WHERE ( username = ?) 
2021-08-13 14:26:49.160 DEBUG 14636 --- [           main] com.hikktn.mapper.UserMapper.deleteUser  : ==> Parameters: hikktn(String)
2021-08-13 14:26:49.170 DEBUG 14636 --- [           main] com.hikktn.mapper.UserMapper.deleteUser  : <==    Updates: 5



版权声明:本文为qq_41520636原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。