MyBatis Introduction, Setup Steps, and Dynamic Proxy Implementation
This article provides a comprehensive guide to MyBatis, covering its basic concepts, Maven dependency configuration, XML setup, entity and mapper definitions, execution flow using dynamic proxies, and a custom lightweight framework implementation with full Java code examples.
Hello everyone, I am a senior architect.
1. MyBatis Introduction
MyBatis is an ORM tool that encapsulates JDBC operations and simplifies business programming; it integrates with Spring in web projects to provide database read/write capabilities.
2. Usage Steps
1. Add Dependencies
Use Maven to include the mybatis-3.5.5 dependency and the MySQL driver.
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>2. Configuration File
Create an XML configuration that defines the data source, environment, and mapper locations.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!-- Database connection -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/user"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- Register mapper files -->
<mappers>
<mapper resource="mybatis/User.xml"/>
</mappers>
</configuration>3. Interface Definition
Define the entity class and the mapper interface.
package com.xiongxin.mybatis.entity;
public class User {
private String username;
private String password;
// getters & setters
} package com.xiongxin.mybatis.mapper;
import com.xiongxin.mybatis.entity.User;
import java.util.List;
public interface UserMapper {
List<User> queryUser();
}Create the XML mapper file that maps the SQL query to the method.
<?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="com.xiongxin.mybatis.mapper.UserMapper">
<select id="queryUser" resultType="com.xiongxin.mybatis.entity.User">
select * from tbl_user
</select>
</mapper>4. Load and Execute
Use MyBatis to build a SqlSessionFactory, obtain the mapper, and execute the query.
package com.xiongxin.mybatis;
import com.alibaba.fastjson.JSON;
import com.xiongxin.mybatis.entity.User;
import com.xiongxin.mybatis.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.Reader;
import java.util.List;
public class TestMain {
public static void main(String[] args) throws Exception {
String resource = "mybatis-config.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> users = userMapper.queryUser();
System.out.println(JSON.toJSONString(users));
}
}
// Output example: [{"password":"password","username":"xiongxin"}]At this point the MyBatis usage is complete.
3. Principle Analysis
The framework obtains a dynamic proxy for the mapper interface, leveraging JDK dynamic proxy mechanisms. The proxy intercepts method calls, retrieves the associated SQL via annotations, and executes it through a MethodInvoker, ultimately returning the result set.
4. Handcrafted Framework
Below is a lightweight custom implementation that mimics MyBatis behavior using annotations, reflection, and JDBC.
package com.dbutil.session;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
/**
* Custom annotation for SQL queries
*/
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface QueryList { String value(); }
public class SqlSession {
public static Connection getConnH2() throws Exception {
String url = "jdbc:h2:mem:db_h2;MODE=MYSQL;INIT=RUNSCRIPT FROM './src/main/resources/schema.sql'";
Class.forName("org.h2.Driver");
return DriverManager.getConnection(url, "root", "123456");
}
public static <T> T getMapper(Class<T> mapperInterface) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, new MapperInvocationHandler());
}
static class MapperInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String sql = method.getAnnotation(QueryList.class).value();
Class<?> returnType = method.getReturnType();
if (returnType == List.class) {
Type generic = method.getGenericReturnType();
String typeName = generic.getTypeName().replace("java.util.List<", "").replace(">", "");
Class<?> elementClass = Class.forName(typeName);
return queryList(sql, elementClass);
}
return null;
}
}
public interface ResultMap<T> { T convert(ResultSet rs) throws Exception; }
public static <T> List<T> queryList(String sql, ResultMap<T> mapper) throws Exception {
Connection conn = getConnH2();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
List<T> list = new ArrayList<>();
while (rs.next()) {
list.add(mapper.convert(rs));
}
rs.close(); st.close(); conn.close();
return list;
}
public static <T> List<T> queryList(String sql, Class<T> clazz) throws Exception {
return queryList(sql, rs -> {
T obj = clazz.newInstance();
for (Field f : clazz.getDeclaredFields()) {
f.setAccessible(true);
if (f.getType() == String.class) {
f.set(obj, rs.getString(f.getName()));
} else if (f.getType() == Long.class) {
f.set(obj, rs.getLong(f.getName()));
}
}
return obj;
});
}
}Additional resources, promotional links, and community invitations are included throughout the original article but are not part of the technical tutorial.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
