一、传统开发方式
1、基础工程代码
-
数据库环境
CREATE DATABASE `mybatis_db`; USE `mybatis_db`; CREATE TABLE `user` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `username` VARCHAR(32) NOT NULL COMMENT '用户名称', `birthday` DATETIME DEFAULT NULL COMMENT '生日', `sex` CHAR(1) DEFAULT NULL COMMENT '性别', `address` VARCHAR(256) DEFAULT NULL COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8; -- insert.... INSERT INTO USER(id,username,birthday,sex,address) VALUES (1,'张三','2024-01-01 00:00:00','男','北京'),(2,'李四','2023-01-01 00:00:00','男','上海');
-
pom依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>mybatis-dao</artifactId> <version>1.0-SNAPSHOT</version> <!--指定编码及版本--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <java.version>1.11</java.version> <maven.compiler.source>1.11</maven.compiler.source> <maven.compiler.target>1.11</maven.compiler.target> </properties> <!--引入相关依赖--> <dependencies> <!--引入mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.3</version> </dependency> <!--引入mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--引入junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project>
-
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///mybatis_db?useSSL=false&characterEncoding=UTF-8 jdbc.username=root jdbc.password=root
-
SqlMapConfig.xml
<?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> <properties resource="jdbc.properties"></properties> <typeAliases> <!--方式一:给单个实体起别名--> <!-- <typeAlias type="domain.User" alias="user"></typeAlias>--> <!--方式二:批量起别名 别名就是类名,且不区分大小写--> <package name="domain"/> </typeAliases> <!--环境配置--> <environments default="mysql"> <!--使用mysql环境--> <environment id="mysql"> <!--使用jdbc事务管理亲--> <transactionManager type="JDBC"></transactionManager> <!-- 使用连接池--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!--加载映射配置--> <mappers> <mapper resource="UserMapper.xml"></mapper> </mappers> </configuration>
-
UserMapper.xml
<?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="user"> <!-- 查询所有用户 --> <select id="findAll" resultType="user"> select * from user </select> <!--根据id查找用户--> <select id="selectById" parameterType="int" resultType="user"> select * from user where id=#{id} </select> <!--新增用户--> <!--#{} : mybatis中的占位符,等同于JDBC中的 parameterType :指定接收到的参数类型 --> <insert id="save" parameterType="domain.User"> insert into user(username, birthday, sex, address) values (#{username}, #{birthday}, #{sex}, #{address}) </insert> <!-- 更新用户 --> <update id="update" parameterType="domain.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> <!--删除用户 java.lang.Integer--> <delete id="delete" parameterType="int"> delete from user where id = #{id} </delete> </mapper>
-
User类
package domain; import java.util.Date; public class User { private Integer id; private String username; private Date birthday; private String sex; private String address; @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
2、基于dao层的代码修改
- 编写UserMapper接口
package mapper;
import domain.User;
public interface UserMapper {
public User findUserById(int id) throws Exception;
}
- 编写UserMapper实现
package mapper.impl;
import domain.User;
import 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.InputStream;
public class UserMapperImpl implements UserMapper {
@Override
public User findUserById(int id) throws Exception {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行sql
User user = sqlSession.selectOne("user.selectById", id);
sqlSession.close();
return user;
}
}
-
测试代码
package test; import domain.User; import mapper.UserMapper; import mapper.impl.UserMapperImpl; import org.junit.Test; public class MybatisTest { @Test public void testFindUserById() throws Exception { UserMapper mapper = new UserMapperImpl(); User user = mapper.findUserById(1); System.out.println(user); } }
-
测试结果
二、传统方式有哪些问题?
-
模板代码重复:
实现类(即DAO层的具体实现)中通常需要编写大量模板化的代码来与MyBatis的SqlSession进行交互,如打开会话、执行SQL、处理结果集以及关闭会话等。这些操作在每个DAO方法中都会出现,造成代码冗余。 -
SQL硬编码耦合:
在Java实现类的方法中直接调用XML映射文件中的SQL statement时,往往需要硬编码具体的statement ID到Java代码中,导致了SQL语句和业务逻辑的紧密耦合,不便于维护和管理。 -
设计复杂性增加:
每个数据访问对象(DAO)都需要对应的接口和实现类,增加了项目的复杂性和工作量,并且使得项目架构不够简洁和易于扩展。
针对上述问题,MyBatis通过动态代理机制提供了优化方案:
MyBatis利用Java的动态代理技术,允许开发者只定义接口而不需编写其实现类。只需在接口方法上添加注解或在Mapper XML文件中配置SQL语句,MyBatis会在运行时自动生成接口的代理对象,该代理对象能够自动处理与数据库的交互过程,包括获取SqlSession、执行映射的SQL、处理结果并关闭会话等操作。这样不仅消除了模板代码重复的问题,同时也降低了SQL与Java代码之间的耦合度,使开发更加模块化和易维护。