从Servlet+JSP+JDBC到MyBatis:重构用户CRUD操作的高效之旅

前言

原生的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:

新增如下依赖

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

XML 复制代码
### 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%n

log4j.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 复制代码
<?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&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;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时,为了保证映射关系的正确配置,将传递多个参数的情况全部封装成对象,并通过对应的对象作为参数传递)

java 复制代码
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:

java 复制代码
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:

java 复制代码
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 复制代码
<?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为映射的根节点,用来管理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 复制代码
<?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&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;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支持
java 复制代码
 
 @Override
    protected 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项目的实现步骤,源代码我会上传到资源中

相关推荐
北方有星辰zz10 分钟前
数据结构:栈
java·开发语言·数据结构
Seven9712 分钟前
一个static关键字引发的线上故障:深度剖析静态变量与配置热更新的陷阱
java
山野万里__14 分钟前
C++与Java内存共享技术:跨平台与跨语言实现指南
android·java·c++·笔记
风象南15 分钟前
Spring Shell命令行工具开发实战
java·spring boot·后端
Java技术小馆20 分钟前
POST为什么发送两次请求
java·面试·架构
天天摸鱼的java工程师21 分钟前
MySQL表设计实战指南:从业务场景到表结构优化
java·后端·mysql
SimonKing23 分钟前
Java处理PDF就靠它!Apache PDFBox:开源免费的PDF全能王
java·后端·程序员
天天摸鱼的java工程师27 分钟前
Java与AI:从业务场景到代码实现,构建人工客服系统实战
java·后端·面试
都叫我大帅哥29 分钟前
Redis中zset内存变形记
java·redis
slowlybutsurely36 分钟前
Cursor快速入门
java·ai编程·cursor