手写mybatis-预编译前的sql语句

sql表 mybatis数据库中的gxa_user表

/*
 Navicat Premium Data Transfer

 Source Server         : root
 Source Server Type    : MySQL
 Source Server Version : 80028
 Source Host           : localhost:3306
 Source Schema         : mybatis

 Target Server Type    : MySQL
 Target Server Version : 80028
 File Encoding         : 65001

 Date: 05/06/2024 20:48:12
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for gxa_user
-- ----------------------------
DROP TABLE IF EXISTS `gxa_user`;
CREATE TABLE `gxa_user`  (
  `id` bigint(0) 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,
  `salt` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `created` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
  `last_login_time` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
  `status` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 47 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of gxa_user
-- ----------------------------
INSERT INTO `gxa_user` VALUES (1, '强哥', 'RbWEEsXVVxiR765qwusODQ==', 'e46d82f4-66b1-457d-8e70-36232b0a656e', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (2, '张老师', 'RbWEEsXVVxiR765qwusODQ==', 'e46d82f4-66b1-457d-8e70-36232b0a656e', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (3, '王国强', 'RbWEEsXVVxiR765qwusODQ==', 'e46d82f4-66b1-457d-8e70-36232b0a656e', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (11, '噗噗', '123456', '111', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (16, '噗噗2', '123456', '111', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (17, '补补', '123456', '111', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (20, '补补', '123456', '111', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (21, 'map', '8888', '222', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (23, 'map', '8888', '222', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (28, '123456', '12345', '123455', '123456', '2024-06-03 21:45:15', '2024-06-03 21:45:15', 1);
INSERT INTO `gxa_user` VALUES (29, 'gxaUser', '12345', '123455', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (30, 'mybatis', '12345', '123455', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (31, 'mybatis', '12345', '123455', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (32, 'mybatis', '12345', '123455', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (33, 'mybatisdemo', '123456', '11', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (34, 'mybatisdemo', '123456', '11', '123456789', '2024-06-03 21:42:18', '2024-06-03 21:42:18', 1);
INSERT INTO `gxa_user` VALUES (35, 'mybatisdemo', '123456', '11', '123568', '2024-06-03 21:47:49', '2024-06-03 21:47:49', 1);
INSERT INTO `gxa_user` VALUES (36, 'mybatisdemo', '123456', '11', '123568', '2024-06-03 21:50:22', '2024-06-03 21:50:22', 1);
INSERT INTO `gxa_user` VALUES (42, 'mybatis', '12345', '123455', '1234556', '2024-06-03 22:02:47', NULL, 1);
INSERT INTO `gxa_user` VALUES (43, 'mybatis', '12345', '123455', '1234556', '2024-06-03 22:04:07', '2024-06-03 22:04:07', 1);
INSERT INTO `gxa_user` VALUES (44, 'mybatis', '12345', '123455', '1234556', '2024-06-03 22:06:07', '2024-06-03 22:06:07', 1);
INSERT INTO `gxa_user` VALUES (45, 'mybatis', '12345', '123455', '1234556', '2024-06-05 14:38:22', '2024-06-05 14:38:22', 1);
INSERT INTO `gxa_user` VALUES (46, 'mybatis', '12345', '123455', '1234556', '2024-06-05 16:15:04', '2024-06-05 16:15:04', 1);

SET FOREIGN_KEY_CHECKS = 1;

jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456

准备五个注解放在annotation包里面

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Delete {
    String value() default "";
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Insert {
    String value() default "";
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Select {
    String value() default "";
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Update {
    String value() default "";
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Param {
    String value() default "";
}

配置数据库连接以及事务

import com.alibaba.druid.pool.DruidDataSource;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcUtils {
    public static DataSource dataSource;
    public static Properties properties=new Properties();
    public static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();

    static {
        try {
            InputStream resourceAsStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            properties.load(resourceAsStream);
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setDriverClassName(properties.getProperty("jdbc.driver"));
            druidDataSource.setUrl(properties.getProperty("jdbc.url"));
            druidDataSource.setUsername(properties.getProperty("jdbc.username"));
            druidDataSource.setPassword(properties.getProperty("jdbc.password"));
            dataSource=druidDataSource;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
    public static Connection getConnection(){
        try {
            if (threadLocal.get()==null)
                threadLocal.set(dataSource.getConnection());
                return threadLocal.get();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    public static void close(){
        if (threadLocal.get()!=null){
            try{
                threadLocal.get().close();
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("连接关闭失败");
            }
            threadLocal.set(null);
        }
    }
    public static void rollback(){
        if(threadLocal.get()!=null){
            try{
                threadLocal.get().rollback();
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("回滚失败");
            }
        }

    }
    public static void commit(){
        if (threadLocal.get()!=null){
            try{
                threadLocal.get().commit();
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("提交失败");
            }

        }

    }
    public static void start(){

            try{
                getConnection().setAutoCommit(false);
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("开启事务失败");
            }


    }

}

根据上面的表创建javabean实体类

/**
 * (GxaUser)实体类
 *
 * @author makejava
 * @since 2024-05-24 15:16:19
 */
public class GxaUser{
    
    private Long id;
    
    private String username;
    
    private String password;
    
    private String salt;
    
    private String phone;
    
    private LocalDateTime created;
    
    private LocalDateTime last_login_time;
    
    private Integer status;


    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;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public LocalDateTime getCreated() {
        return created;
    }

    public void setCreated(LocalDateTime created) {
        this.created = created;
    }

    public LocalDateTime getLastLoginTime() {
        return last_login_time;
    }

    public void setLastLoginTime(LocalDateTime lastLoginTime) {
        this.last_login_time = lastLoginTime;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "GxaUser{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", salt='" + salt + '\'' +
                ", phone='" + phone + '\'' +
                ", created=" + created +
                ", lastLoginTime=" + last_login_time +
                ", status=" + status +
                '}';
    }
}

Dto传输参数给数据库的

public class GxaUserDto {

    
    private String username;
    
    private String password;
    
    private String salt;
    
    private String phone;
    
    private Date created;
    
    private Date last_login_time;
    
    private Integer status;



    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;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getLastLoginTime() {
        return last_login_time;
    }

    public void setLastLoginTime(Date lastLoginTime) {
        this.last_login_time = lastLoginTime;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "GxaUser{" +
                " username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", salt='" + salt + '\'' +
                ", phone='" + phone + '\'' +
                ", created=" + created +
                ", lastLoginTime=" + last_login_time +
                ", status=" + status +
                '}';
    }
}

mapper接口类

import com.ssj.annotation.Delete;
import com.ssj.annotation.Insert;
import com.ssj.annotation.Select;
import com.ssj.annotation.Update;
import com.ssj.entity.GxaUser;
import com.ssj.entity.GxaUserDto;
import com.ssj.entity.GxaUserDto2;

import java.util.HashMap;
import java.util.List;

public interface GxaUserMapper {
    @Select("Select * from gxa_user where id=?")
    GxaUser findUserById(Long id);
    @Select("Select * from gxa_user")
    List<GxaUser> findUser();
    @Insert("Insert into gxa_user(username,password,salt,phone,created,last_login_time,status)\n" +
            "        values(?,?,?,?,?,?,?)")
    int insertUser(GxaUserDto user);
    @Update("update gxa_user set username=? where id=?")
    int update(String username,Long id);
    @Delete("Delete from gxa_user where id=?")
    int delete(Long id);
}

sql语句预编译工具类


import java.util.ArrayList;
import java.util.List;


public class SQLUtils {


    /**
     * 将SQL字符串中的命名参数替换为"?"占位符。
     *
     * @param sql 包含命名参数的SQL查询字符串,格式为#{paramName}。
     * @param selectParams 要替换的参数名称列表。
     * @return 将命名参数替换为"?"占位符后的SQL查询字符串。
     */
    public static String replaceParam(String sql, List<Object> selectParams) {
        // 遍历参数名称列表
        for (int i = 0; i < selectParams.size(); i++) {
            // 获取当前的参数名称
            Object paramName = selectParams.get(i);
            // 将SQL字符串中出现的命名参数替换为"?"
            sql = sql.replace("#{" + paramName + "}", "?");
        }
        // 返回修改后的SQL字符串
        return sql;
    }

    /**
     * 将SQL字符串中的命名参数替换为"?"占位符。
     *
     * @param sql 包含命名参数的SQL查询字符串,格式为#{paramName}。
     * @param parameterName 要替换的参数名称数组。
     * @return 将命名参数替换为"?"占位符后的SQL查询字符串。
     */
    public static String replaceParam(String sql, String[] parameterName) {
        // 遍历参数名称数组
        for (int i = 0; i < parameterName.length; i++) {
            // 获取当前的参数名称并去除前后的空白字符
            String string = parameterName[i].trim();
            // 将SQL字符串中出现的命名参数替换为"?"
            sql = sql.replace("#{" + string + "}", "?");
        }
        // 返回修改后的SQL字符串
        return sql;
    }

    /**
     * 从SQL查询字符串的WHERE子句中提取参数名称列表。
     *
     * @param sql 包含WHERE子句和命名参数的SQL查询字符串。
     * @return 从WHERE子句中提取的参数名称列表。
     */
    public static List<Object> getSelectParams(String sql) {
        List<Object> paramList = new ArrayList<>();

        // 查找WHERE子句的起始索引
        int whereIndex = sql.toLowerCase().indexOf("where");
        if (whereIndex == -1) {
            // 如果没有WHERE子句,返回空列表
            return paramList;
        }

        // 从SQL字符串中提取WHERE子句
        String whereClause = sql.substring(whereIndex + 5).trim();
        if (whereClause.isEmpty()) {
            // 如果WHERE子句为空,返回空列表
            return paramList;
        }

        // 按"and"分割WHERE子句,得到各个条件
        String[] paramsStrs = whereClause.split("\\s+and\\s+");
        // 遍历每个条件
        for (String paramsStr : paramsStrs) {
            // 按"="分割条件,提取参数
            if (paramsStr.contains("=")) {
                String[] parts = paramsStr.split("=");
                if (parts.length == 2) {
                    String param = parts[1].replace("#{", "").replace("}", "").trim();
                    if (!param.isEmpty()) {
                        // 将参数名称添加到列表中
                        paramList.add(param);
                    }
                }
            }
        }
        // 返回参数名称列表
        return paramList;
    }

    /**
     * 从INSERT SQL查询字符串的VALUES子句中提取参数名称列表。
     *
     * @param sql 包含INSERT语句和命名参数的SQL查询字符串。
     * @return 从VALUES子句中提取的参数名称数组。
     */
    public static String[] getInsertParams(String sql) {
        // 查找VALUES子句的起始索引
        int startIndex = sql.indexOf("values");
        // 从SQL字符串中提取VALUES子句,去除参数名称中的#{和},并去除括号
        String values = sql.substring(startIndex + 6).replaceAll("#\\{", "").replaceAll("}", "").
                replace("(", "").replace(")", "");
        // 按逗号分割清理后的VALUES子句,得到各个参数名称
        return values.split(",");
    }

    public static List<Object> getUpdateParams(String sql) {
        List<Object> paramList = new ArrayList<>();

        // 查找SET子句的起始索引
        int setStartIndex = sql.toLowerCase().indexOf("set") + 3;
        int whereStartIndex = sql.toLowerCase().indexOf("where");

        // 如果没有WHERE子句
        if (whereStartIndex == -1) {
            // 提取整个SET子句
            String setClause = sql.substring(setStartIndex).trim();
            addSetParams(paramList, setClause);
        } else {
            // 提取SET子句中的参数
            String setClause = sql.substring(setStartIndex, whereStartIndex).trim();
            addSetParams(paramList, setClause);

            // 提取WHERE子句中的参数
            String whereClause = sql.substring(whereStartIndex + 5).trim();
            addWhereParams(paramList, whereClause);
        }

        return paramList;

    }
    // 辅助方法:提取SET子句中的参数
    private static void addSetParams(List<Object> paramList, String setClause) {
        String[] setParams = setClause.split(",");
        for (String setParam : setParams) {
            String param = setParam.split("=")[1].replace("#{", "").replace("}", "").trim();
            paramList.add(param);
        }
    }
    // 辅助方法:提取WHERE子句中的参数
    private static void addWhereParams(List<Object> paramList, String whereClause) {
        String[] whereParams = whereClause.split("\\s+and\\s+");
        for (String whereParam : whereParams) {
            if (whereParam.contains("=")) {
                String[] parts = whereParam.split("=");
                if (parts.length == 2) {
                    String param = parts[1].replace("#{", "").replace("}", "").trim();
                    if (!param.isEmpty()) {
                        paramList.add(param);
                    }
                }
            }
        }
    }
}

jdk动态地理实现上面mapper接口

import com.ssj.annotation.*;

import java.lang.reflect.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class MybatisUtils {
    public static <T> T getMapper(Class<T> clazz) {
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("该 " + method.getName() + " 方法被调用了");
                if (method.isAnnotationPresent(Insert.class)) {
                    Insert annotation = method.getAnnotation(Insert.class);
                    String sql = annotation.value();
                    return executeInsert(method,sql, args);
                } else if (method.isAnnotationPresent(Delete.class)) {
                    Delete annotation = method.getAnnotation(Delete.class);
                    String sql = annotation.value();
                    return executeDelete(method,sql, args);
                } else if (method.isAnnotationPresent(Update.class)) {
                    Update annotation = method.getAnnotation(Update.class);
                    String sql = annotation.value();
                    return executeUpdate(method,sql, args);
                } else if (method.isAnnotationPresent(Select.class)) {
                    Select annotation = method.getAnnotation(Select.class);
                    String sql = annotation.value();
                    return executeQuery(sql, args, method);
                }
                return null;
            }

            private int executeInsert(Method method,String sql, Object[] args) throws Exception {
                if (args.length == 0) {
                    System.out.println("args长度为0");
                    throw new IllegalArgumentException("Invalid argument for insert operation");
                }
                //插入参数
                String[] insertParam = SQLUtils.getInsertParams(sql);
                //参数绑定
                ConcurrentHashMap<String, Object> paramMap = getMethodParam(method, args);
                //将参数值加入list
                List<Object> paramValueList = addParamToList(insertParam, paramMap);
                //预编译sql语句
                sql = SQLUtils.replaceParam(sql, insertParam);

                try (Connection connection = JdbcUtils.getConnection();
                     PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
                    JdbcUtils.start();
//                    setPreparedStatementParameters(preparedStatement, args[0]);
                    if (paramValueList!=null){
                        // 设置PreparedStatement参数
                        for (int i = 0; i < paramValueList.toArray().length; i++) {
                            // 将方法参数设置到PreparedStatement中
                            preparedStatement.setObject(i + 1, paramValueList.get(i));
                        }
                    }

                    int rows = preparedStatement.executeUpdate();
                    JdbcUtils.commit();
                    return rows;
                }catch (Exception e){
                    JdbcUtils.rollback();
                    JdbcUtils.commit();
                    e.printStackTrace();
                    throw new RuntimeException("数据库连接异常");
                }finally {
                    JdbcUtils.close();
                }
            }
            private int executeUpdate(Method method,String sql, Object[] args) throws Exception {
                //插入参数
                List<Object> insertParam = SQLUtils.getUpdateParams(sql);
                //参数绑定
                ConcurrentHashMap<String, Object> paramMap = getMethodParam(method, args);
                //将参数值加入list
                List<Object> paramValueList = addParamToList(insertParam, paramMap);
                //预编译sql语句
                sql = SQLUtils.replaceParam(sql, insertParam);
                try (Connection connection = JdbcUtils.getConnection();
                     PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
                    JdbcUtils.start();
                    for (int i = 0; i < paramValueList.toArray().length; i++) {
                        System.out.println("修改参数: " + args[i]);
                        preparedStatement.setObject(i + 1, paramValueList.get(i));
                    }

                    int rows = preparedStatement.executeUpdate();
                    JdbcUtils.commit();
                    return rows;
                } catch (Exception e) {
                    JdbcUtils.rollback();
                    throw e;
                } finally {
                    JdbcUtils.close();
                }
            }
            private int executeDelete(Method method,String sql, Object[] args) throws Exception {
                //插入参数
                List<Object> insertParam = SQLUtils.getSelectParams(sql);
                //参数绑定
                ConcurrentHashMap<String, Object> paramMap = getMethodParam(method, args);
                //将参数值加入list
                List<Object> paramValueList = addParamToList(insertParam, paramMap);
                //预编译sql语句
                sql = SQLUtils.replaceParam(sql, insertParam);
                try (Connection connection = JdbcUtils.getConnection();
                     PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
                    JdbcUtils.start();
                    for (int i = 0; i < paramValueList.toArray().length; i++) {
                        System.out.println("删除参数: " + args[i]);
                        preparedStatement.setObject(i + 1, paramValueList.get(i));
                    }

                    int rows = preparedStatement.executeUpdate();
                    JdbcUtils.commit();
                    return rows;
                } catch (Exception e) {
                    JdbcUtils.rollback();
                    throw e;
                } finally {
                    JdbcUtils.close();
                }
            }

            // 执行查询操作
            private Object executeQuery(String sql, Object[] args, Method method) throws Exception {
                //插入参数
                List<Object> selectParams = SQLUtils.getSelectParams(sql);
                //参数绑定
                ConcurrentHashMap<String, Object> paramMap = getMethodParam(method, args);
                //将参数值加入list
                List<Object> paramValueList = addParamToList(selectParams, paramMap);
                //预编译sql语句
                sql = SQLUtils.replaceParam(sql, selectParams);
                try (Connection connection = JdbcUtils.getConnection();
                     PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
                    System.out.println("args.length="+args);
                    if (args!=null){
                        // 设置PreparedStatement参数
                        for (int i = 0; i < paramValueList.toArray().length; i++) {
                            // 将方法参数设置到PreparedStatement中
                            preparedStatement.setObject(i + 1, paramValueList.get(i));
                        }
                    }
                    // 执行查询操作
                    ResultSet resultSet = preparedStatement.executeQuery();

                    // 获取方法的返回类型
                    Class<?> returnType = method.getReturnType();
                    // 如果返回类型是List,则将结果集映射为List对象
                    if (returnType == List.class) {
                        return mapResultSetToList(resultSet, getGenericReturnType(method));
                    } else {
                        // 如果不是List,则将结果集映射为单个对象
                        if (resultSet.next()) {
                            return mapResultSetToObject(resultSet, returnType);
                        }
                    }
                    return null;
                }catch (Exception e){
                    e.printStackTrace();
                    throw new RuntimeException("数据库连接异常");
                }finally {
                    JdbcUtils.close();
                }
            }

            private void setPreparedStatementParameters(PreparedStatement preparedStatement, Object param) throws Exception {
                System.out.println(param);
                Class<?> clazz = param.getClass();
                Field[] fields = clazz.getDeclaredFields();
                int index = 1;

                for (Field field : fields) {
                    field.setAccessible(true);
                    Object value = field.get(param);
                    System.out.println("insert--- 参数:"+value);
//                    if (value==null) continue;
                    preparedStatement.setObject(index++, value);
                }
            }



            // 将ResultSet映射为对象列表
            private <T> List<T> mapResultSetToList(ResultSet resultSet, Class<T> clazz) throws Exception {
                List<T> list = new ArrayList<>();
                // 遍历结果集,将每行数据映射为对象并添加到列表中
                while (resultSet.next()) {
                    list.add(mapResultSetToObject(resultSet, clazz));
                }
                return list;
            }

            // 将ResultSet映射为单个对象
            private <T> T mapResultSetToObject(ResultSet resultSet, Class<T> clazz) throws Exception {
                T obj = clazz.getDeclaredConstructor().newInstance();
                ResultSetMetaData metaData = resultSet.getMetaData();
                // 遍历结果集的元数据,将每列的数据映射到对象的相应字段中
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    String columnName = metaData.getColumnName(i);
                    Field field = clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(obj, resultSet.getObject(i));
                }
                return obj;
            }

            // 获取方法的泛型返回类型
            private Class<?> getGenericReturnType(Method method) {
                Type returnType = method.getGenericReturnType();
                // 如果返回类型是参数化类型,则获取实际的类型参数
                if (returnType instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) returnType;
                    return (Class<?>) parameterizedType.getActualTypeArguments()[0];
                }
                return Object.class;
            }
            // 判断一个类是否为基本类型或包装类型
            private  boolean isPrimitiveOrWrapper(Class<?> type) {
                return type.isPrimitive() || type == Boolean.class || type == Byte.class ||
                        type == Character.class || type == Double.class || type == Float.class ||
                        type == Integer.class || type == Long.class || type == Short.class ||
                        type == String.class;
            }

            private ConcurrentHashMap<String, Object> getMethodParam(Method method, Object[] args) {
                ConcurrentHashMap<String, Object> paramMap = new ConcurrentHashMap<>();
                Parameter[] parameters = method.getParameters();
                for (int i = 0; i < parameters.length; i++) {
                    Param param = parameters[i].getAnnotation(Param.class);
                    if (param == null) {
                        continue;
                    }
                    String paramName = param.value();
                    System.out.println("paramName="+paramName);
                    Object paramValue = args[i];
                    System.out.println("paramValue="+paramValue);

                    // 如果参数不是基本类型或包装类型,则将其属性名和值添加到 paramMap 中
                    if (!isPrimitiveOrWrapper(paramValue.getClass())) {
                        addObjectFieldsToParamMap(paramMap, paramName, paramValue);
                    } else {
                        paramMap.put(paramName, paramValue);
                    }
                }
                return paramMap;
            }

            // 将对象的属性名和值添加到 paramMap 中
            private void addObjectFieldsToParamMap(ConcurrentHashMap<String, Object> paramMap, String paramName, Object paramValue) {
                Field[] fields = paramValue.getClass().getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    try {
                        Object fieldValue = field.get(paramValue);
                        System.out.println("filedValue="+fieldValue);
                        String fieldName = paramName + "." + field.getName();
                        System.out.println("fieldName="+fieldName.substring(fieldName.indexOf(".")+1));
                        paramMap.put(fieldName.substring(fieldName.indexOf(".")+1), fieldValue);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
            private List<Object> addParamToList(String[] insertParam, ConcurrentHashMap<String, Object> paramMap) {
                List<Object> paramValueList = new ArrayList<>();
                for (String param : insertParam) {
                    Object paramValue = paramMap.get(param.trim());
                    paramValueList.add(paramValue);
                }
                return paramValueList;
            }
            private List<Object> addParamToList(List<Object> insertParam, ConcurrentHashMap<String, Object> paramMap) {
                List<Object> paramValueList = new ArrayList<>();
                for (Object param : insertParam) {
                    Object paramValue = paramMap.get(param);
                    paramValueList.add(paramValue);
                }
                return paramValueList;
            }

        });
    }
}

在这里插入图片描述

项目结构

在这里插入图片描述
完整代码,请移步gitee
https://gitee.com/xiaobei_xiaohe/mybatisDemo2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/694437.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ Easyx案例实战:Cookie Maker工作室1.0V

前言 //制作属于自己的工作室&#xff01; 注&#xff1a;运行效果以及下载见Cookie Maker 工作室成立程序。 关于Cookie Maker工作室成立的信息&#xff0c;I am very happy&#xff08;唔……改不过来了&#xff09;。 OKOK&#xff0c;第一次用图形库写程序&#xff08;图形…

一分钟有60秒,这个有趣的原因你知道吗?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【JavaEE】Spring IoCDI详解

一.基本概念 1.Ioc基本概念 Ioc: Inversion of Control (控制反转), 也就是说 Spring 是⼀个"控制反转"的容器. 什么是控制反转呢? 也就是控制权反转. 什么的控制权发发了反转? 获得依赖对象的过程被反转了也就是说, 当需要某个对象时, 传统开发模式中需要自己通…

minio的一个基础使用案例:用户头像上传

文章目录 一、minio下载安装&#xff08;Windows&#xff09;二、案例需求分析三、后端接口开发 一、minio下载安装&#xff08;Windows&#xff09; 1. 下载minio服务端和客户端 minio下载地址 2. 手动搭建目录 /minio/binmc.exeminio.exe/data/logs手动创建minio应用程序目…

66. UE5 RPG 实现远程攻击武器配合角色攻击动画

在制作游戏中&#xff0c;我们制作远程攻击角色&#xff0c;他们一般会使用弓箭&#xff0c;弩&#xff0c;弹弓等武器来进行攻击。比如你使用弓箭时&#xff0c;如果角色在播放拉弓弦的动画&#xff0c;但是弓箭武器没有对应的表现&#xff0c;会显得很突兀。所以&#xff0c;…

GDPU Java 天码行空15 数据库编程

一、实验目的 1、 了解数据库的基础知识。 2、 掌握MySQL的下载、安装与配置。 3、 掌握MySQL可视化工具的使用。 4、 了解SQL语言。 5、 掌握JDBC中的API&#xff0c;并能进行简单的数据库操作。 二、实验内容 1、 安装MySQL &#x1f468;‍&#x1f3eb; 视频教程 2、建…

私有云和多云管理平台 | Cloudpods v3.11.4 正式发布

本次 3.11.4 更新亮点为&#xff1a;系统镜像引入社区镜像&#xff0c;用户可以一键导入各主流开源操作系统镜像&#xff0c;方便用户上手使用。持续迭代共享 LVM&#xff0c;支持快照&#xff0c;主备机等特性&#xff0c;修复迁移删除镜像缓存等 BUG。 功能优化 【费用】费…

linux动态调试 dev_dbg

动态调试使用方法 打开内核动态调试开关&#xff0c;make menuconfig选中CONFIG_DYNAMIC_DEBUG以及CONFIG_DEBUG_FS Linux启动后&#xff0c;使用命令行挂载上dbgfs 1. mkdir /mnt/dbg 2. mount -t debugfs none /mnt/dbg 1.控制某个文件所有dev_dbg()&#xff0c; echo -n &q…

mongodb总概

一、mongodb概述 mongodb是最流行的nosql数据库&#xff0c;由C语言编写。其功能非常丰富&#xff0c;包括: 面向集合文档的存储:适合存储Bson(json的扩展)形式的数据;格式自由&#xff0c;数据格式不固定&#xff0c;生产环境下修改结构都可以不影响程序运行;强大的查询语句…

MSPM0l1306——配置滴答定时器

我们配置好了滴答定时器之后&#xff0c;还要手动编写滴答定时器的中断服务函数&#xff0c;因为我们开启的滴答定时器的中断&#xff0c;当滴答定时器的计数值从我们设置的值减到0时&#xff0c;就会触发一次中断&#xff0c;触发中断就会执行中断服务函数。各个中断的中断服务…

144、二叉树的前序递归遍历

题解&#xff1a; 递归书写三要素&#xff1a; 1&#xff09;确定递归函数的参数和返回值。要确定每次递归所要用到的参数以及需要返回的值 2&#xff09;确定终止条件。操作系统也是用栈的方式实现递归&#xff0c;那么如果不写终止条件或者终止条件写的不对&#xff0c;都…

Here Doucument

一、Here Document概述 1.概念 使用I/0重定向的方式将命令列表提供给交互式程序 标准输入的一种替代品 2.语法格式 命令 <<标记 标记 3.注意事项 标记可以使用任意合法字符&#xff08;通常为EOF&#xff09; 结尾的标记一定要顶格写&#xff0c;前面不能有任何字符…

【iOS】内存泄漏检查及原因分析

目录 为什么要检测内存泄漏&#xff1f;什么是内存泄漏&#xff1f;内存泄漏排查方法1. 使用Zombie Objects2. 静态分析3. 动态分析方法定位修改Leaks界面分析Call Tree的四个选项&#xff1a; 内存泄漏原因分析1. Leaked Memory&#xff1a;应用程序未引用的、不能再次使用或释…

Java数据结构准备工作---常用类

文章目录 前言1.包装类1.1.包装类基本知识1.2.包装类的用途1.3.装箱和拆箱1.3.1.装箱&#xff1a;1.3.2.拆箱 1.4 包装类的缓存问题 2.时间处理类2.1.Date 时间类(java.util.Date)2.2.DateFormat 类和 SimpleDateFormat 类2.3.Calendar 日历类 3.其他常用类3.1.Math类3.2.Rando…

嵌入式中C语言经典的面试题分享

#error的作用是什么? #error 指令让预处理器发出一条错误信息,并且会中断编译过程。下面我们从Linux代码中抽取出来一小段代码并做修改得到示例代码: 这段示例代码很简单,当RX_BUF_IDX宏的值不为0~3时,在预处理阶段就会通过 #error 指令输出一条错误提示信息: "…

Python 很好用的爬虫框架:Scrapy:

了解Scrapy 爬虫框架的工作流程&#xff1a; 在scrapy中&#xff0c; 具体工作流程是这样的&#xff1a; 首先第一步 当爬虫引擎<engine>启动后&#xff0c; 引擎会到 spider 中获取 start_url<起始url> 然后将其封装为一个request对象&#xff0c; 交给调度器<…

文心一言 VS 讯飞星火 VS chatgpt (277)-- 算法导论20.3 4题

四、如果调用 vEB-TREE-INSERT 来插入一个已包含在 vEB 树中的元素&#xff0c;会出现什么情况&#xff1f;如果调用 vEB-TREE-DELETE 来删除一个不包含在 vEB 树中的元素&#xff0c;会出现什么情况&#xff1f;解释这些函数为什么有相应的运行状况&#xff1f;怎样修改 vEB 树…

【手推公式】如何求SDE的解(附录B)

【手推公式】如何求SDE的解&#xff08;附录B&#xff09; 核心思路&#xff1a;不直接求VE和VP的SDE的解xt&#xff0c;而是求xt的期望和方差&#xff0c;从而写出x0到xt的条件分布形式&#xff08;附录B&#xff09; 论文&#xff1a;Score-Based Generative Modeling throug…

【SpringBoot + Vue 尚庭公寓实战】根据类型查询标签列表接口实现(五)

【SpringBoot Vue 尚庭公寓实战】根据类型查询标签列表接口实现&#xff08;五&#xff09; 文章目录 【SpringBoot Vue 尚庭公寓实战】根据类型查询标签列表接口实现&#xff08;五&#xff09;1、查看接口2、进行开发 1、查看接口 启动项目 访问&#xff1a;http://localho…

快排(快速排序)的递归与非递归实现(文末附完整代码)

快排有几种不同的写法&#xff0c;下面一一来介绍并实现。其中又分为递归和非递归的写法&#xff0c;但大体思路相同&#xff0c;只是代码实现略有不同。(注&#xff1a;文章中的完整代码中&#xff0c;Swap()函数均省略未写&#xff0c;记得自己补充) 递归写法 递归的写法类…