一、传统开发方式
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 configurationPUBLIC "-//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 mapperPUBLIC "-//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;@Overridepublic 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 {@Overridepublic User findUserById(int id) throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();//执行sqlUser 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 {@Testpublic 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代码之间的耦合度,使开发更加模块化和易维护。