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() {
@Override
public 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。。。。