当前位置: 首页 > article >正文

面向接口的方式进行CRUD

CRUD是什么意思?

CRUD说的就是增查改删
C:就是创建(Create)
R:就是查找(Retrieve)
U:就是更改(Update)
D:就是删除(Delete)

什么是面向接口方式进行CRUD?

在传统的JavaWeb开发中DAO(Data Access Object)层通常需要你手写接口和实现类,接口定义了数据库操作方法,而实现类则具体实现这些方法,使用JDBC或其他持久化技术进行数据库操作。

但是在MyBatis框架中你只需要定义DAO接口,MyBatis会根据XML配置文件或注解自动生成接口的实现类。这样就不需要手动编写实现类了,减少了大量的代码工作。其背后的原理是MyBatis使用动态代理来为这些接口生成实现类,执行SQL操作。

具体来说:

  1. 手写DAO层:通常需要手动编写两个部分:

    • DAO接口:定义基本的CRUD方法。
    • DAO实现类:通过JDBC等方式编写具体的数据库操作逻辑。
      public interface UserDao {
          User findUserById(int id);
      }
      
      public class UserDaoImpl implements UserDao {
          @Override
          public User findUserById(int id) {
              // JDBC logic to find user by id
          }
      }
      

2. MyBatis中的DAO层:只需编写DAO接口,并通过MyBatis的XML映射文件或注解绑定SQL语句,MyBatis会自动生成实现类。

示例:

  • DAO接口:
    public interface UserDao {
        User findUserById(int id);
    }
    

    XML映射文件(UserMapper.xml):

    <select id="findUserById" parameterType="int" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>
    

    MyBatis通过动态代理机制自动实现了UserDao接口的实现类并执行对应的SQL查询,使得开发者可以更加专注于业务逻辑,而无需处理底层的数据访问实现。

知识点介绍:

getMapper 是 MyBatis 框架中的一个常用方法,用于获取映射器(Mapper)。映射器是 MyBatis 中的接口,它负责与数据库进行交互。通过 getMapper 方法,你可以动态获取这些映射器的实例,并调用其中定义的数据库操作方法。接下来是关于 getMapper 的一些知识点。

1. 基本概念

在 MyBatis 中,映射器(Mapper)是一个接口,定义了数据访问的方法。MyBatis 框架通过 getMapper 方法为这个接口生成具体的实现类,并且这个实现类会自动执行与数据库的交互逻辑

2. getMapper 的用法

getMapper 通常用于从 MyBatis 的 SqlSession 中获取映射器的实例。你可以通过映射器直接调用数据库的操作方法,而无需手动编写数据库访问代码。代码示例:

// 1. 获取 SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();

// 2. 获取映射器
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

// 3. 使用映射器进行数据库操作
User user = userMapper.findUserById(1);

// 4. 关闭 SqlSession
sqlSession.close();

在上面的例子中:

  • UserMapper 是一个定义了数据库操作方法的接口。
  • sqlSession.getMapper(UserMapper.class) 返回了 UserMapper 接口的实现类实例,并通过这个实例可以直接调用数据库查询方法。

使用的前提条件:

  1. AccountMapper.xml 文件中的 namespace

    • XML 文件的 <mapper> 标签需要设置 namespace,其值必须是 DAO 接口的全限定名(即包路径+类名)
      <mapper namespace="com.example.dao.AccountDao">
      
  2. id 必须和接口方法名一致

    • XML 中每个 SQL 映射的 <select>, <insert> 等标签的 id 必须与 AccountDao 接口中的方法名一致。

      <select id="findById" resultType="com.example.domain.Account">
          SELECT * FROM account WHERE id = #{id}
      </select>
      
    • 对应的 DAO 接口方法:

      Account findById(int id);
      

    这样,当调用 accountDao.findById() 时,MyBatis 会根据接口的代理类自动映射到 AccountMapper.xml 中的 id="findById" 这段 SQL。

实例:

dao层 

CarMapper接口

package dao;

import pojo.Car;

import java.util.List;

public interface CarMapper {
    /**
     * 新增汽车信息
     * @param car
     * @return 返回新增条数
     */
    int insert(Car car);

    /**
     * 根据id值删除汽车信息
     * @param id
     * @return 返回删除条数
     */
    int deleteById(Long id);

    /**
     * 根据id值更新
     * @param car
     * @return 返回更新条数
     */
    int update(Car car);

    /**
     * 获取所有汽车信息
     * @return 返回Car的集合
     */
    List<Car> selectAll();
}

pojo层(Model层内部):

Car类:

package pojo;

public class Car {
    private int id;
    private String carNum;
    private String brand;
    private double guidePrice;
    private String produceTime;
    private String carType;

    public Car() {
    }

    public Car(int id,String carNum, String brand, double guidePrice,String produceTime,String carType) {
        this.brand = brand;
        this.carNum = carNum;
        this.carType = carType;
        this.guidePrice = guidePrice;
        this.id = id;
        this.produceTime = produceTime;
    }

    // Getters and setters
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCarNum() {
        return carNum;
    }

    public void setCarNum(String carNum) {
        this.carNum = carNum;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public double getGuidePrice() {
        return guidePrice;
    }

    public void setGuidePrice(double guidePrice) {
        this.guidePrice = guidePrice;
    }

    public String getProduceTime() {
        return produceTime;
    }

    public void setProduceTime(String produceTime) {
        this.produceTime = produceTime;
    }

    public String getCarType() {
        return carType;
    }

    public void setCarType(String carType) {
        this.carType = carType;
    }

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", carNum='" + carNum + '\'' +
                ", brand='" + brand + '\'' +
                ", guidePrice=" + guidePrice +
                ", produceTime='" + produceTime + '\'' +
                ", carType='" + carType + '\'' +
                '}';
    }
}

Util包:

运用该类则需要进行手动提交

package util;

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.IOException;
import java.io.InputStream;

public class SqlSessionUtil {
    // 静态SqlSessionFactory对象,用于保证整个应用程序中只有一个SqlSessionFactory实例
    private static SqlSessionFactory sqlSessionFactory;

    // 静态代码块,用于类加载时初始化SqlSessionFactory对象
    static {
        try {
            // 读取MyBatis配置文件,构建SqlSessionFactory对象
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.XML");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);  // 捕获IO异常并抛出运行时异常
        }
    }


    // 全局的,服务器级别的,一个服务器当中定义一个即可
    private static ThreadLocal<SqlSession> local  = new ThreadLocal<>();
    /**
     * 获取SqlSession对象
     * @return SqlSession对象
     */
    public static SqlSession openSession() {
        SqlSession sqlSession = local.get();
        if (sqlSession==null){
             sqlSession = sqlSessionFactory.openSession();
             // 将sqlSession对象绑定子啊当前线程上 保证一个线程是一个sqlSession对象
             local.set(sqlSession);
        }
        return sqlSession;
    }

    /**
     * 关闭SqlSession对象从当前线程移除sqlSession对象
     * @param sqlSession 要关闭的SqlSession对象
     */
    public static void closeSession(SqlSession sqlSession) {
        if (sqlSession != null) {
            sqlSession.close();  // 关闭会话
            // 移除SqlSession对象和线程的绑定关系
            // 因为Tomcat服务器支持线程池。也就是说:用过的线程对象t1,可能下一次还会使用这个t1线程。
            local.remove();
        }
    }
}

配置文件 

carMapper.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="dao.CarMapper">
 <!--这里的namespace一定要是接口的全限定名称-->

    <!-- insert语句 id 是sql语句的唯一标识,这个id就代表了这条sql语句 -->
    <insert id="insert">
        insert into t_car(id, car_num, brand, guide_price, produce_time, car_type)
        values(null, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType})
    </insert>

    <delete id="deleteById">
        delete from t_car where id = #{id}
    </delete>

    <update id="update">
        update t_car set
                         car_num = #{carNum},
                         brand = #{brand},
                         guide_price = #{guidePrice},
                         produce_time = #{produceTime},
                         car_type = #{carType}
        where id = #{id}
    </update>
 <!--注意,select语句都需要取别名,不然sql上的数据对应不上类中数据-->
    <select id="selectAll" resultType="pojo.Car">
        select
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
        from t_car
    </select>

</mapper>

mybatis-config.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">  <!-- 如果你需要使用非连接池类型,可以替换为 UNPOOLED -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/testmybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>  <!--自己的用户密码-->
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="carMapper.XML"/> <!--一定要在这里配置不然找不到接口-->
    </mappers>
</configuration>


http://www.kler.cn/news/368621.html

相关文章:

  • pdf压缩如何操作?教你8招,轻松搞定文件压缩!
  • 医学数据分析中的偏特征图可视化
  • Liunx权限概念及权限管理
  • Linux:指令再认识
  • 深入理解跳出率:如何利用百度统计优化网站用户体验
  • type C 引脚定义
  • 排序算法(冒泡,插入),希尔排序(插入升级),希尔排序和插入排序时间比较!
  • C++:多态(用法篇)
  • webpack解决使用window.open方法打开history路由页面提示404的问题
  • linux softirq tasklet 软中断实现
  • AGI大模型面经汇总,太全了!收藏一下吧很难找全的!
  • 2-135 基于matlab的有限差分法计算电位分布
  • Linux系统设置开机自启动.py脚本(树莓派Ubuntu)
  • 使用虚拟机搭建环境:CentOS7 Docker、MySQL、Redis 安装与配置
  • 微信小程序美团点餐
  • 【软件工程】软件项目管理/工程项目管理复习资料
  • Rust: [u8] 与 String 相互转换
  • JavaScript(操作元素属性:样式style,className,classList,表单元素,自定义属性,间歇函数)注册用户协议同意倒计时
  • 【论文笔记】MLSLT: Towards Multilingual Sign Language Translation
  • 数据结构之 二叉树详解一 介绍篇
  • 如何提高游戏的游戏性
  • 电动汽车与软件定义汽车(SDV)时代的汽车行业变革
  • 【机器学习-无监督学习】自编码器
  • First - Word Fall - Through ( FWFT ) Read Operation
  • 【制造业&PPE】施工安全防护装备检测系统源码&数据集全套:改进yolo11-RVB-EMA
  • ubuntu20上部署gitlab并开启ipv6访问