首页 > 其他分享 >简易mybatis实现

简易mybatis实现

时间:2023-12-27 15:25:36浏览次数:29  
标签:java String 实现 简易 offset mybatis import com public

package com.ibatis.io.entity;


public class User {
  private Integer id;
  private String name;

  private Integer age;

  public Integer getId() {
      return id;
  }

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

  public String getName() {
      return name;
  }

  public void setName(String name) {
      this.name = name;
  }

  public Integer getAge() {
      return age;
  }

  public void setAge(Integer age) {
      this.age = age;
  }

  @Override
  public String toString() {
      return "User{" +
              "id=" + id +
              ", name='" + name + '\'' +
              ", age=" + age +
              '}';
  }
}
package com.ibatis.io.mapper;

import com.ibatis.io.entity.User;
import com.ibatis.io.mybatis.Param;
import com.ibatis.io.mybatis.Select;

import java.util.List;


public interface UserMapper {

  @Select("select * from user where name=#{name}")
  public List<User> getUser(@Param("name") String name,@Param("age") Integer age);

  @Select("select * from user where id=#{id}")
  public User getUserById(@Param("id") Integer id);
}


package com.ibatis.io.mybatis;

public class GenericTokenParser {

  private final String openToken;
  private final String closeToken;
  private final TokenHandler handler;

  public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {
      this.openToken = openToken;
      this.closeToken = closeToken;
      this.handler = handler;
  }

  public String parse(String text) {
      if (text == null || text.isEmpty()) {
          return "";
      }
      // search open token
      int start = text.indexOf(openToken, 0);
      if (start == -1) {
          return text;
      }
      char[] src = text.toCharArray();
      int offset = 0;
      final StringBuilder builder = new StringBuilder();
      StringBuilder expression = null;
      while (start > -1) {
          if (start > 0 && src[start - 1] == '\\') {
              // this open token is escaped. remove the backslash and continue.
              builder.append(src, offset, start - offset - 1).append(openToken);
              offset = start + openToken.length();
          } else {
              // found open token. let's search close token.
              if (expression == null) {
                  expression = new StringBuilder();
              } else {
                  expression.setLength(0);
              }
              builder.append(src, offset, start - offset);
              offset = start + openToken.length();
              int end = text.indexOf(closeToken, offset);
              while (end > -1) {
                  if (end > offset && src[end - 1] == '\\') {
                      // this close token is escaped. remove the backslash and continue.
                      expression.append(src, offset, end - offset - 1).append(closeToken);
                      offset = end + closeToken.length();
                      end = text.indexOf(closeToken, offset);
                  } else {
                      expression.append(src, offset, end - offset);
                      offset = end + closeToken.length();
                      break;
                  }
              }
              if (end == -1) {
                  // close token was not found.
                  builder.append(src, start, src.length - start);
                  offset = src.length;
              } else {
                  builder.append(handler.handleToken(expression.toString()));
                  offset = end + closeToken.length();
              }
          }
          start = text.indexOf(openToken, offset);
      }
      if (offset < src.length) {
          builder.append(src, offset, src.length - offset);
      }
      return builder.toString();
  }
}
package com.ibatis.io.mybatis;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class IntegerTypeHandler implements TypeHandler<Integer> {
  @Override
  public void setParameter(PreparedStatement statement, int i, Integer value) throws SQLException {
      statement.setInt(i, value);
  }

  @Override
  public Integer getResult(ResultSet rs, String columnName) throws SQLException {
      return rs.getInt(columnName);
  }
}
package com.ibatis.io.mybatis;


import java.lang.reflect.*;
import java.sql.*;
import java.util.*;


public class MapperProxyFactory {

  private static final Map<Class<?>, TypeHandler> typeHandlerMap = new HashMap<>();



  static {
      try {
          typeHandlerMap.put(String.class, new StringTypeHandler());
          typeHandlerMap.put(Integer.class, new IntegerTypeHandler());
          Class.forName("com.mysql.cj.jdbc.Driver");
      } catch (ClassNotFoundException e) {
          throw new RuntimeException(e);
      }
  }

  public static <T> T getMapper(Class<T> mapper) {
      Object proxyInstance = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{mapper}, new InvocationHandler() {
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              // 获取数据库连接
              Connection conn = getConnection();
              Select annotation = method.getAnnotation(Select.class);
              String sql = annotation.value();

              Parameter[] parameters = method.getParameters();
              HashMap<String, Object> map = new HashMap<>();
              for (int i = 0; i < parameters.length; i++) {
                  String parameter = parameters[i].getAnnotation(Param.class).value();
                  map.put(parameter, args[i]);
              }

              // 解析 SQL,并将 #{} 替换为 ?
              ParameterMappingTokenHandler tokenHandler = new ParameterMappingTokenHandler();
              GenericTokenParser parser = new GenericTokenParser("#{", "}", tokenHandler);
              String parse = parser.parse(sql);
              // 结果支持List或单个User对象
              Object result = null;
              // 执行 SQL
              List<Object> users;

              ResultSetMetaData metaData;
              try (PreparedStatement preparedStatement = conn.prepareStatement(parse)) {
                  List<ParameterMapping> parameterMappings = tokenHandler.getParameterMappings();
                  for (int i = 0; i < parameterMappings.size(); i++) {
                      String property = parameterMappings.get(i).getProperty();
                      Class<?> aClass = map.get(property).getClass();
                      typeHandlerMap.get(aClass).setParameter(preparedStatement, i + 1, map.get(property));

                  }
                  preparedStatement.execute();
                  Class resultType = null;
                  Type genericReturnType = method.getGenericReturnType();
                  if (genericReturnType instanceof Class) {
                      resultType = (Class) genericReturnType;
                  } else if (genericReturnType instanceof ParameterizedType) {
                      Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
                      resultType = (Class) actualTypeArguments[0];
                  }
                  users = new ArrayList<>();
                  metaData = preparedStatement.getMetaData();
                  List<String> columnList = new ArrayList<>();
                  for (int i = 0; i < metaData.getColumnCount(); i++) {
                      columnList.add(metaData.getColumnName(i + 1));
                  }

                  HashMap<String, Method> setMap = new HashMap<>();
                  for (Method declaredMethod : resultType.getDeclaredMethods()) {
                      if (declaredMethod.getName().startsWith("set")) {
                          String substring = declaredMethod.getName().substring(3);
                          substring = substring.substring(0, 1).toLowerCase(Locale.ROOT) + substring.substring(1);
                          setMap.put(substring, declaredMethod);
                      }
                  }

                  ResultSet resultSet = preparedStatement.getResultSet();
                  while (resultSet.next()) {
                      Object instance = resultType.getDeclaredConstructor().newInstance();
                      for (int i = 0; i < columnList.size(); i++) {
                          String column = columnList.get(i);
                          Method setMethod = setMap.get(column);
                          Class<?> parameterType = setMethod.getParameterTypes()[0];
                          TypeHandler typeHandler = typeHandlerMap.get(parameterType);
                          setMethod.invoke(instance, typeHandler.getResult(resultSet, column));
                      }
                      users.add(instance);
                  }


                  if (method.getReturnType().equals(List.class)) {
                      result = users;
                  } else {
                      result = users.get(0);
                  }
              }


              return result;
          }
      });
      return (T) proxyInstance;
  }

  private static Connection getConnection() throws SQLException {
      return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC", "root", "123456");
  }


}
package com.ibatis.io.mybatis;

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


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Param {

  String value();
}

package com.ibatis.io.mybatis;

public class ParameterMapping {
  private String property;

  public ParameterMapping(String property) {
      this.property = property;
  }

  public String getProperty() {
      return property;
  }

  public void setProperty(String property) {
      this.property = property;
  }
}
package com.ibatis.io.mybatis;

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

public class ParameterMappingTokenHandler implements TokenHandler {
  private final List<ParameterMapping> parameterMappings = new ArrayList();


  public List<ParameterMapping> getParameterMappings() {
      return this.parameterMappings;
  }

  public String handleToken(String content) {
      this.parameterMappings.add(new ParameterMapping(content));
      return "?";
  }


}
package com.ibatis.io.mybatis;

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

/**
* @Created by ggz
* @Date 2023/12/26 14:01
* @Version 1.0.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {

  String value();
}
package com.ibatis.io.mybatis;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
* @Created by ggz
* @Date 2023/12/26 17:17
* @Version 1.0.0
*/
public class StringTypeHandler implements TypeHandler<String>{
  @Override
  public void setParameter(PreparedStatement statement, int i, String value) throws SQLException {
      statement.setString(i, value);
  }

  @Override
  public String getResult(ResultSet rs, String columnName) throws SQLException {
      return rs.getString(columnName);
  }
}
package com.ibatis.io.mybatis;

public interface TokenHandler {
  String handleToken(String content);
}
package com.ibatis.io.mybatis;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
* @Created by ggz
* @Date 2023/12/26 17:15
* @Version 1.0.0
*/
public interface TypeHandler<T> {
  void setParameter(PreparedStatement statement, int i, T value) throws SQLException;

  T getResult(ResultSet rs, String columnName) throws SQLException;
}
package com.ibatis.io;

import com.ibatis.io.entity.User;
import com.ibatis.io.mapper.UserMapper;
import com.ibatis.io.mybatis.MapperProxyFactory;

import java.util.List;

/**
* @Created by ggz
* @Date 2023/12/26 14:24
* @Version 1.0.0
*/
public class App {
  public static void main(String[] args) {
      UserMapper mapper = MapperProxyFactory.getMapper(UserMapper.class);
      List<User> users = mapper.getUser("小米",20);
      System.out.println(users);
      User userById = mapper.getUserById(2);
      System.out.println(userById);
  }
}
/*
Navicat Premium Data Transfer

Source Server         : local
Source Server Type   : MySQL
Source Server Version : 80027
Source Host           : localhost:3306
Source Schema         : test

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

Date: 27/12/2023 15:14:42
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(0) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`age` int(0) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '小米', 20);
INSERT INTO `user` VALUES (2, '大米', 22);

SET FOREIGN_KEY_CHECKS = 1;
 

标签:java,String,实现,简易,offset,mybatis,import,com,public
From: https://www.cnblogs.com/goPush/p/17930634.html

相关文章

  • Langchain-Chatchat+Qwen实现本地知识库(二)
    在上一篇文章当中,我们已经通过Langchain-Chatchat+Qwen-14b-int4完成了本地知识库的搭建,现在我们通过vue和api接口来做定制的聊天页面,达成下图类似gpt或者其他大模型的显示效果:1.知识库启动:见上一篇文章2.api接口部署:在/Langchain-Chatchat/configs的serve_config文件中可以......
  • 自然语言处理与人工智能:如何实现语言理解和生成
    1.背景介绍自然语言处理(NLP,NaturalLanguageProcessing)是人工智能(AI,ArtificialIntelligence)领域的一个重要分支,主要关注计算机如何理解和生成人类自然语言。自然语言理解(NLU,NaturalLanguageUnderstanding)和自然语言生成(NLG,NaturalLanguageGeneration)是NLP的两大核心任务。自......
  • 自然语言处理的技术路线:如何实现高效的文本分析
    1.背景介绍自然语言处理(NLP)是计算机科学与人工智能的一个分支,研究如何让计算机理解、生成和处理人类语言。自然语言处理的技术路线是一种高效的文本分析方法,它可以帮助我们解决许多实际问题,例如文本摘要、情感分析、文本分类、机器翻译等。在本文中,我们将探讨自然语言处理的核心概......
  • 自然语言处理与大数据:如何实现数据的可视化与交互性
    1.背景介绍自然语言处理(NLP)是人工智能领域的一个重要分支,它涉及计算机对自然语言的理解和生成。随着数据的大量产生,自然语言处理与大数据技术的结合成为了一个热门的研究方向。在这篇文章中,我们将探讨如何实现数据的可视化与交互性,以便更好地理解和应用自然语言处理技术。1.1自然......
  • WPF中实现页面跳转
    `WPF中实现页面跳转WPF是WindowsPresentationFoundation的缩写,是微软推出的一种用于创建桌面应用程序的技术。WPF中有一个重要的概念就是页面(Page),它可以让我们在一个窗口(Window)中显示不同的内容,实现类似于网页浏览器的效果。页面跳转就是指从一个页面切换到另一个页面的过程。......
  • Nacos服务注册与发现的2种实现方法!
    「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。SpringCloudAlibaba技术体系中的Nacos,提供了两个重要的功能:注册中心(服务注册与发现)功能和配置中心功能。其中注册中心解决了微服务调用中,服务提供者和服务调用者的解耦,让程序开发者可以无需过多的关......
  • 实现异步循环--闭包
    让我们试着写一个异步方法,每秒打印一次循环的索引值。for(vari=0;i<5;i++){ setTimeout(function(){ console.log(i); },1000*(i+1));}如上程序的输出为:>5>5>5>5>5这明显是有问题的。原因每次时间结束(timeout)都指向原始的i,而并非它的......
  • Jenkins自动化部署实现原理
     1.jdk环境,Jenkins是java语言开发的,因需要jdk环境。2.git/svn客户端,因一般代码是放在git/svn服务器上的,我们需要拉取代码。3.maven客户端,因一般java程序是由maven工程,需要maven打包,当然也有其他打包方式,如:gradle。4.Jenkins可以不用安装tomcat,只要有Java环境就可以,它可以自己启......
  • 模拟实现strstr函数的代码——《初学C语言第40天》
    //////模拟实现strstr////(字符中的元素是连续存放的,所以不会存在跳动存放的情况,例如a1="ababcd",a2="ac"此结果就是NULL)////情况1.arr1="abcd"arr2="abc"(一次匹配就找到了)////情况2.arr1="ababcd"arr2="abc"(多次匹配才能找到)//#include<stdio.h>//#in......
  • 医学影像的图像标注技术:如何实现自动化的图像标注与分析
    1.背景介绍医学影像是一种重要的诊断工具,用于揭示患者的内部结构和功能。医学影像分析通常需要专业医学影像诊断师对图像进行手工标注和分析,这是一个耗时且容易出错的过程。因此,自动化的图像标注和分析技术在医学影像领域具有重要意义。图像标注是一种计算机视觉任务,旨在将图像中的......