前言
原生的JDBC:
- 原生的JDBC操作数据库,书写较为繁琐,降低开发效率。
- JDBC的局限性(如代码冗余、SQL语句与Java代码紧密耦合、难以维护等)。
相比于JDBC,Mybatis的优势:
- SQL与Java代码的分离、强大的映射能力、易于维护和扩展等。
什么是Mybatis?
MyBatis是一个用于简化数据库操作、提高开发效率的持久层框架,它允许开发者通过简单的配置和映射来直接操作数据库,而无需深入处理JDBC的繁琐细节。
简而言之,Mybatis底层是基于JDBC进行的高级别封装,在简化原生JDBC操作的基础上,提高开发效率
重构用户的CRUD项目
使用Mybatis框架重构项目,可以提高项目的扩展性,为后续框架整合打下基础,这里我会介绍如何使用mybatis框架代替原生JDBC操作数据库的相关操作。
原来项目可以参考我的博客: 实战指南:深度剖析Servlet+JSP+JDBC技术栈下的用户CRUD操作-CSDN博客
这里我主要介绍DAO层的开发
重构步骤如下:
第一步:导入mybatis相关的依赖,和log4j依赖
pom.xml:
新增如下依赖
<!--mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version></dependency><!--log4j--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.7</version></dependency>
注意:添加log4j依赖的目的是为了在mybatis开发过程中查看sql的执行情况,以便快速定位sql的错误位置。并且添加了log4j依赖,需要导入相关的配置文件到resources
log4j.properties
### set log levels ###log4j.rootLogger = debug,stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d %p [%c] - %m%nlog4j.logger.com.ibatis=debug
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug,stdout
第二步:在resources目录下创建mybatis.xml文件作为mybatis的主配置文件
mybatis.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><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver"value="com.mysql.cj.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/csx_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments></configuration>
注意:这里的数据库名以及username和password的value值应当是自己本地mysql服务器上的数据
第三步:创建DAO层,书写与之对应的mapper.xml映射文件
UserDao:
接口和接口方法和重构之前保持差不多,目的都是定义一个实现需求的规范,无论使用JDBC还是mybatis,本质上都是对接口声明的实现。
(下面展示的接口和原本项目的接口有些不同,因为我使用mybatis时,为了保证映射关系的正确配置,将传递多个参数的情况全部封装成对象,并通过对应的对象作为参数传递)
package dao;import entity.User;
import entity.dto.UserDto;
import entity.dto.UserDtoNew;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface UserDao {/*** 查看用户总条数* @return*/int selectUsersCount();/*** 分页查询用户列表* @return*/List<User> selectUserListByPage(UserDto userDto);/*** 新增用户* @param user* @return*/public int insertUser(User user);/*** 根据id查询指定用户信息* @param userId* @return*/public User selectUserByUserId(int userId);/*** 根据id删除用户信息* @param userId* @return*/public int deleteUserByUserId(int userId);/*** 修改用户数据* @param user* @return*/public int updateUser(User user);/*** 根据用户名和密码查看指定用户是否存在* @return*/public User selectUserByuserNameAndpassword(UserDtoNew userDtoNew);}
新增实体类:
UserDto:
package entity.dto;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;import java.io.Serializable;@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class UserDto implements Serializable {private String keyword;private Integer pageIndex;private Integer pageSize;}
UserDtoNew:
package entity.dto;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;import java.io.Serializable;@Getter
@NoArgsConstructor
@AllArgsConstructor
@Setter
public class UserDtoNew implements Serializable {private String userName;private String password;
}
新增实体类的目的是当DAO接口中方法的形参为多个时,将形参封装成对象进行传参,从而可以方便的进行Java的属性和数据库中的字段(列)进行映射。
mapper.xml:
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为映射的根节点,用来管理DAO接口 namespace指定DAO接口的完整类名,表示mapper配置文件管理哪个DAO接口(包.接口名)mybatis会依据这个接口动态创建一个实现类去实现这个接口,而这个实现类是一个Mapper对象-->
<mapper namespace="dao.UserDao"><resultMap id="userMap" type="entity.User"><id property="userId" column="user_id"/><result property="userName" column="user_name"/><result property="userPic" column="user_pic"/></resultMap><insert id="insertUser">insert into t_user (user_name,password,user_pic) values (#{userName},#{password},#{userPic})</insert><update id="updateUser">update t_user set user_name=#{userName},password=#{password},user_pic=#{userPic} where user_id=#{userId}</update><delete id="deleteUserByUserId">delete from t_user where user_id=#{userId}</delete><select id="selectUsersCount" resultType="java.lang.Integer">select count(user_id) from t_user</select><select id="selectUserListByPage" resultMap="userMap" parameterType="entity.dto.UserDto">select * from t_user where user_name like concat('%',#{keyword},'%') order by user_id desc limit #{pageIndex},#{pageSize}</select><select id="selectUserByUserId" resultMap="userMap">select * from t_user where user_id = #{userId}</select><select id="selectUserByuserNameAndpassword" resultMap="userMap">select * from t_user where user_name=#{userName} and password=#{password}</select><!--id = "接口中的方法名"parameterType = "接口中传入方法的参数类型"resultType = "返回实体类对象:包.类名" 处理结果集 自动封装注意:sql语句后不要出现";"号查询:select标签增加:insert标签修改:update标签删除:delete标签-->
</mapper>
注意:
- 因为我使用select * 查询字段,需要配置属性和字段的映射关系,使用<resultMap>标签
- #{}表示的是占位符的含义,这里使用它的含义和使用原生JDBC的preparedstatement预编译sql是一样的
- 当传入的参数为一个时,#{名字可以任意},如果传入的参数是多个,#{对应类的属性名}
第四步:将mapper.xml的配置添加到主配置文件mybatis.xml配置中
mybatis.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><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver"value="com.mysql.cj.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/csx_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><mapper resource="mapper/UserMapper.xml"></mapper></mappers></configuration>
第五步:修改servlet类,使用mybatis获取sql支持
- 在doPost方法中通过SqlSessionfactory创建SqlSession对象,在根据SqlSession对象获取对应的Dao实现类对象(代理对象)。
- 调用Dao接口获取sql支持
@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {SqlSession session= SqlSessionFactoryUtil.getSessionSql();UserDao userDao= session.getMapper(UserDao.class);
//...
}
获取到Dao层的对象之后,获取到对应的数据之后。剩余处理就和未重构之前的操作一样了(细节处有点差异)。
简而言之,就是JSP发送请求到Servlet,Servlet调用DAO获取数据并处理响应。
总结
以上就是使用mybatis替代原生JDBC重构用户CRUD项目的实现步骤,源代码我会上传到资源中