MyBatis 数据处理:主键获取、批量删除与动态表名

MyBatis 数据处理:主键获取、批量删除与动态表名

1.主键获取

XML配置中使用了useGeneratedKeys="true"和keyProperty="id"来自动获取并设置插入后的自增主键。这是一个标准的做法。

1)mapper接口

复制代码
/**
 * 添加数据时获取自增id
 */
int addUserGetId(User user);

2)mapper.xml

复制代码
<!--添加数据时获取自增主键-->
<insert id="addUserGetId" parameterType="org.xiji.enty.User" useGeneratedKeys="true" keyProperty="id">
    insert into user (username,password,userInfo) values(#{username},#{password},#{userInfo})
</insert>

3)测试代码

在测试代码中,user.getId()应该能够返回插入后数据库自动生成的主键值。注意,这需要数据库支持自增主键,并且在JDBC连接中正确配置了自动生成主键的功能。

复制代码
/**
 * 获取添加数据时的主键
 */
@Test
public void testAddUserGetId()
{
    User user = new User();

    user.setUsername("test");
    user.setPassword("123456");
    user.setUserInfo("test");

    int id = specialMapper.addUserGetId(user);
    System.out.println("插入时,主键回显到传入的参数中"+user.getId());
}

4)测试结果

2.批量删除

使用${ids}直接拼接SQL语句的方式存在SQL注入的风险,不建议使用。而使用<foreach>标签则是更安全的方式。

1)mapper接口

1-使用手动拼接字符串数组的方法
复制代码
/**
 * 批量删除
 */
int deleteBatch(String ids);
2-使用mybatis中的foreach标签
复制代码
/**
 * 通过传入的数组
 */
int deleteUserByArray(@Param("array") int[] array);

2)mapper.xml

1-使用手动拼接字符串数组的方法
复制代码
<!--这种是手动拼接 批量删除获取参数-->
<delete id="deleteBatch" >
    delete from user where id in (${ids})
</delete>
2-使用mybatis中的foreach标签
复制代码
<!--通过传入的数组-->
<!--批量删除获取参数-->
<delete id="deleteUserByArray" >
    delete from user where id  in 
                     <foreach collection="array" item="id" open="(" separator="," close=")">
                         #{id}
                     </foreach>
</delete>

3)测试代码

对于使用<foreach>标签的方法,测试代码看起来是正确的。注意,@Param("array") int[] array这样的参数传递方式是正确的,MyBatis会识别数组并正确地将其传递给SQL语句。

1-使用手动拼接字符串数组的方法
复制代码
/**
 * 批量删除的特殊处理
 */
@Test
public void testDeleteBatch()
{
//    手动把输入传入的集合转化为字符串,传入
    
    int result = specialMapper.deleteBatch("4,5,6");
    System.out.println(result);
}
2-使用mybatis中的foreach标签
复制代码
/**
 * 通过传入数组批量删除
 */
@Test
public void testAddUserByArray()
{
    int[] array = {2,7};
    int result = specialMapper.deleteUserByArray(array);
    System.out.println(result);
}

4)测试结果

1-使用手动拼接字符串数组的方法
2-使用mybatis中的foreach标签

这里删除第二条和第一条数据

3.动态设置表名

动态设置表名时,使用${tableName}可以直接将变量值嵌入到SQL语句中,但这同样存在SQL注入的风险。如果tableName是从外部输入获得的话,请务必进行严格的验证和过滤。

1)mapper接口

复制代码
/**
 * 动态设置表名
 */
@MapKey("id")
List<Map<String,Object>> getUserByTableName(String tableName);

2)mapper.xml

复制代码
/**
 * 动态设置表名
 */
@MapKey("id")
List<Map<String,Object>> getUserByTableName(String tableName);

3)测试代码

在测试代码中,动态设置表名的功能得到了验证,但是要注意在实际应用中确保表名的安全性。

复制代码
/**
 * 动态获取设置表名
 */
@Test
public void testGetUserByTableName()

{
    System.out.println("查询第一张表");
    List<Map<String, Object>> user = specialMapper.getUserByTableName("user");
    for (int i = 0; i < user.size(); i++) {
        System.out.println(user.get(i).toString());
    }
    System.out.println(user);
    System.out.println("======================================================");
    System.out.println("查询第二张表");
    List<Map<String, Object>> user2 = specialMapper.getUserByTableName("user2");
    for (int i = 0; i < user2.size(); i++) {
        System.out.println(user2.get(i).toString());
    }
    System.out.println(user2);

}

4)测试结果

user表的数据

user2表内容

5)扩展(水平分表的查询实现)

对于水平分表的情况,需要根据ID来决定查询哪个表。在这个例子中,queryUserByTableName方法接收两个参数:id和tableName。然后根据id的值来决定查询哪个表。这种方式在处理分表的情况下是有效的,但同样要注意表名的安全性。

例:现在我们有一张表数据量太多了,想要垂直分表

下面是思路

user表有6条数据

我们想要从3号id开始垂直分,分到user2表中

1-mapper接口
复制代码
/**
 * 水平分表
 */
List<User> queryUserByTableName(@Param("id") int id,@Param("tableName") String tableName);
2-mapper.xml
复制代码
<!--水平分表查询-->
<select id="queryUserByTableName"  resultType="org.xiji.enty.User" >
    select * from ${tableName} where id=#{id}

</select>
3-test代码
复制代码
@Test
public void testQueryUserByTableName2()
{
    //用于接受数据
    List<User> userList =null;
    int id = 2;


    /**
     * 随机查询
     */

    for (int i = 0; i < 6; i++) {
        id = (int) (Math.random()*6);
        /*如果id等于零那就赋值唯1*/
        if (id == 0) {
            id = 1;
        }
        System.out.println("======================================================");
        System.out.println("请输入要查询的id");
        //传入查询id
        if (id < 4 && id > 0) {
            userList = specialMapper.queryUserByTableName(id, "user");
        }
        if (id > 3 && id < 7) {
            userList=specialMapper.queryUserByTableName(id,"user2");
        }


        for (int j = 0; j < userList.size(); j++) {
            User user = userList.get(j);
            System.out.println(user.toString());

        }
    }



}
4-测试结果

附录:

1 SpecialMapper文件

java 复制代码
package org.xiji.mapper;

import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.xiji.enty.User;

import java.util.List;
import java.util.Map;

@Mapper
public interface SpecialMapper {
    /**
     * 批量删除
     */
    int deleteBatch(@Param("ids") String ids);

    /**
     * 动态设置表名
     */
    @MapKey("id")
    List<Map<String,Object>> getUserByTableName(@Param("tableName") String tableName);

    /**
     * 添加数据时获取自增id
     */
    int addUserGetId(User user);

    /**
     * 通过传入的数组
     */
    int deleteUserByArray(@Param("array") int[] array);

    /**
     * 水平分表
     */
    List<User> queryUserByTableName(@Param("id") int id,@Param("tableName") String tableName);
}

2 SpecialMapper.xml文件

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="org.xiji.mapper.SpecialMapper">

    <!--添加数据时获取自增主键-->
    <insert id="addUserGetId" parameterType="org.xiji.enty.User" useGeneratedKeys="true" keyProperty="id">
        insert into user (username,password,userInfo) values(#{username},#{password},#{userInfo})
    </insert>
    <insert id="addUserByArray"></insert>

    <!--通过传入的数组-->
    <!--批量删除获取参数-->
    <delete id="deleteUserByArray" >
        delete from user where id  in
                         <foreach collection="array" item="id" open="(" separator="," close=")">
                             #{id}
                         </foreach>
    </delete>



    <!--动态设置表名-->
    <select id="getUserByTableName" resultType="java.util.Map">
        select * from ${tableName}
    </select>
    <!--水平分表查询-->
    <select id="queryUserByTableName"  resultType="org.xiji.enty.User" >
        select * from ${tableName} where id=#{id}

    </select>


</mapper>

3.SpecialMaperTest文件

java 复制代码
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.xiji.enty.User;
import org.xiji.mapper.SpecialMapper;

import java.util.List;
import java.util.Map;
import java.util.Scanner;

@SpringJUnitConfig(locations = {"classpath:springConfig.xml"})
public class SpecialMapperTest {
    @Autowired
    private SpecialMapper specialMapper;


    /**
     * 获取添加数据时的主键
     */
    @Test
    public void testAddUserGetId()
    {
        User user = new User();

        user.setUsername("test");
        user.setPassword("123456");
        user.setUserInfo("test");

        int id = specialMapper.addUserGetId(user);
        System.out.println("插入时,主键回显到传入的参数中"+user.getId());
    }

    /**
     * 批量删除的特殊处理
     */
    @Test
    public void testDeleteBatch()
    {

        int result = specialMapper.deleteBatch("4,5,6");
        System.out.println(result);
    }

    /**
     * 动态获取设置表名
     */
    @Test
    public void testGetUserByTableName()

    {
        System.out.println("查询第一张表");
        List<Map<String, Object>> user = specialMapper.getUserByTableName("user");
        for (int i = 0; i < user.size(); i++) {
            System.out.println(user.get(i).toString());
        }
        System.out.println(user);
        System.out.println("======================================================");
        System.out.println("查询第二张表");
        List<Map<String, Object>> user2 = specialMapper.getUserByTableName("user2");
        for (int i = 0; i < user2.size(); i++) {
            System.out.println(user2.get(i).toString());
        }
        System.out.println(user2);

    }

    /**
     * 通过传入数组批量删除
     */
    @Test
    public void testAddUserByArray()
    {
        int[] array = {2,7};
        int result = specialMapper.deleteUserByArray(array);
        System.out.println(result);
    }

    /**
     * 水平分表查询
     */
    @Test
    public void testQueryUserByTableName()
    {


        /**
         * 模拟查询
         */


        //传入查询id
        int id = 2;
        List<User> user = specialMapper.queryUserByTableName(id, "user");
        User user1 = user.get(0);
        String username = user1.getUsername();
        System.out.println(username);
        System.out.println("======================================================");
            id = 5;

        List<User> user2 = specialMapper.queryUserByTableName(id, "user2");
        User user3 = user2.get(0);
        String username2 = user3.getUsername();
        System.out.println(username2);


    }

    @Test
    public void testQueryUserByTableName2()
    {
        //用于接受数据
        List<User> userList =null;
        int id = 2;


        /**
         * 随机查询
         */

        for (int i = 0; i < 6; i++) {
            id = (int) (Math.random()*6);
            /*如果id等于零那就赋值唯1*/
            if (id == 0) {
                id = 1;
            }
            System.out.println("======================================================");
            System.out.println("请输入要查询的id");
            //传入查询id
            if (id < 4 && id > 0) {
                userList = specialMapper.queryUserByTableName(id, "user");
            }
            if (id > 3 && id < 7) {
                userList=specialMapper.queryUserByTableName(id,"user2");
            }


            for (int j = 0; j < userList.size(); j++) {
                User user = userList.get(j);
                System.out.println(user.toString());

            }
        }



    }



}

4.user表

sql 复制代码
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名字',
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户密码',
  `userInfo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户信息',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;
相关推荐
一只叫煤球的猫7 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9658 小时前
tcp/ip 中的多路复用
后端
bobz9658 小时前
tls ingress 简单记录
后端
皮皮林5519 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友9 小时前
什么是OpenSSL
后端·安全·程序员
bobz9659 小时前
mcp 直接操作浏览器
后端
前端小张同学12 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook12 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康13 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在13 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net