http://mybatis.org/spring/zh/getting-started.html https://mybatis.net.cn/getting-started.html
一、回顾 jdbc
获取链接—》预编译sql—》设置参数—》执行sql
public class JdbcReview {public static void main(String[] args) {try {Class.forName("com.mysql.cj.jdbc.Driver'");} catch (ClassNotFoundException e) {e.printStackTrace();}Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {connection = DriverManager.getConnection("");statement = connection.createStatement();resultSet = statement.executeQuery("select * from user");List<User> users = new ArrayList<>();while (resultSet.next()) {User user = new User();user.setId(resultSet.getInt(1));user.setAge(resultSet.getInt(2));user.setName(resultSet.getString(3));users.add(user);}} catch (Exception e) {e.printStackTrace();} finally {if (resultSet != null) {try {resultSet.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}}
- 1、statement中的execute方法
- boolean execute(String sql) throws SQLException;
- true:第一个结果是一个结果集
- false:更新操作或者无结果集
- 2、executeUpdate
- int executeUpdate(String sql) throws SQLException;
- (1) DML语言的操作行数
- 3、executeQuery
- ResultSet executeQuery(String sql) throws SQLException;
- 查询返回结果集
二、整体架构设计
三、sql解析过程
interface UserMapper {@Select("SELECT * FROM user WHERE age = #{age} and name = #{name}")List<User> selectUserList(int age, String name);}public class MyBatisMapperProxy {public static void main(String[] args) {UserMapper userMapper = (UserMapper) Proxy.newProxyInstance(MyBatisMapperProxy.class.getClassLoader(), new Class<?>[]{UserMapper.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Select annotation = method.getAnnotation(Select.class);Map<String, Object> nameArgMap = buildMethodArgNameMap(method, args);if (annotation != null) {String[] value = annotation.value();String sql = value[0];// 解析sql,用参数替换 #{}sql = parseSql(sql, nameArgMap);// 这就拿到组装好的sql了System.out.println(sql);System.out.println(method.getReturnType());System.out.println(method.getGenericReturnType());System.out.println(method.getGenericReturnType().getClass());}return null;}});userMapper.selectUserList(1, "king");}public static String parseSql(String sql, Map<String, Object> nameArgMap) {StringBuilder stringBuilder = new StringBuilder();int length = sql.length();for (int i = 0; i < length; i++) {char c = sql.charAt(i);if (c == '#') {int nextIndex = i + 1;char nextChar = sql.charAt(nextIndex);if (nextChar != '{') {throw new RuntimeException(String.format("这里应该为#{\nsql:%s\nindex:%d", stringBuilder.toString(), nextIndex));}StringBuilder argSB = new StringBuilder();i = parseSQLArg(argSB, sql, nextIndex + 1);String argName = argSB.toString();Object argValue = nameArgMap.get(argName);stringBuilder.append(argValue.toString());continue;}stringBuilder.append(c);}return stringBuilder.toString();}private static int parseSQLArg(StringBuilder argSB, String sql, int nextIndex) {for (; nextIndex < sql.length(); nextIndex++) {char c = sql.charAt(nextIndex);if (c != '}') {argSB.append(c);continue;}// 找到右括号就返回if (c == '}') {return nextIndex;}}throw new RuntimeException(String.format("缺少右括号#{\nsql:%s\nindex:%d", sql, nextIndex));}public static Map<String, Object> buildMethodArgNameMap(Method method, Object[] args) {HashMap<String, Object> map = new HashMap<>();Parameter[] parameters = method.getParameters();if (parameters.length != args.length) {System.out.println("s错误。。。");throw new RuntimeException("error,,.....");}int index[] = {0};Arrays.stream(parameters).forEach(parameter -> {// 注意:使用此方法需要开启IDEA支持带参数名编译,否则会出现 arg0,arg1// https://blog.csdn.net/lcgoing/article/details/88537836// Preferences -> "Build, Execution, Deployment" -> Compiler -> "Java Compiler"// "Project bytecode version"设置为1.8// "Additional command line parameters"添加"-parameters"String name = parameter.getName();System.out.println(name);map.put(name, args[index[0]]);index[0]++;});return map;}}
这里拿到了解析完的sql,然后将这个sql放到 第一节 里执行即可。
这就是一个简化简化的mybatis。。。。
