mybatis的CRUD

本文详细介绍了MyBatis框架的CRUD操作,包括搭建项目环境、动态代理、配置核心文件如properties、typeAliases和mappers,以及如何进行查询、新增、修改和删除用户等操作。还探讨了占位符的使用、主键获取、事务管理和多种参数输入类型。通过实例解析了mapper接口和映射文件的编写,帮助读者深入理解MyBatis的DAO层开发。
摘要由CSDN通过智能技术生成

《MyBatis的CRUD》

带着目标去学习,效果很不一样

学习目标

  1. 掌握sqlMapConfig.xml中常用标签
  2. 掌握mybatis框架在DAO层的开发
  3. 能够完成单表的CRUD操作
  4. 掌握mybatis框架的输入输出映射

回顾动态代理

代理模式的组成

作用:对真实角色功能的增强,真实角色和代理角色都是抽象角色的子类

  1. 抽象角色:定义了要实现的功能,通常使用接口。这个案例中就是UserMapper接口
  2. 真实角色:可以不存在的,这里没有
  3. 代理角色:也实现了接口中方法,使用动态代理来实现UserMapper接口,并且重写其中方法: findAllUsers()

在这里插入图片描述

动态代理的好处

  1. 接口的代理对象由程序在执行的过程中动态生成,不用我们自己去写一个类实现接口中所有的方法
  2. 可以动态生成任意接口的对象

Proxy类中的方法

在这里插入图片描述

InvocationHandler接口

在这里插入图片描述

模拟查询所有用户的方法

package com.itheima.utils;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 访问数据库的工具类
 */
public class JdbcUtils {
   
    //可以把几个字符串定义成常量:用户名,密码,URL,驱动类
    private static final String USER = "root";
    private static final String PWD = "root";
    private static final String URL = "jdbc:mysql://localhost:3306/day24";
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    /**
     * 注册驱动,为了兼容1.5以前的版本
     */
    static {
   
        try {
   
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
   
            e.printStackTrace();
        }
    }

    /**
     * 得到数据库的连接
     */
    public static Connection getConnection() throws SQLException {
   
        return DriverManager.getConnection(URL, USER, PWD);
    }

    /**
     * 关闭连接
     * 查询调用这个方法
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
   
        try {
   
            if (resultSet != null) {
   
                resultSet.close();
            }
        } catch (SQLException e) {
   
            e.printStackTrace();
        }
        try {
   
            if (statement != null) {
   
                statement.close();
            }
        } catch (SQLException e) {
   
            e.printStackTrace();
        }
        try {
   
            if (connection != null) {
   
                connection.close();
            }
        } catch (SQLException e) {
   
            e.printStackTrace();
        }
    }


    /**
     * 关闭连接
     * 增删改没有结果集
     */
    public static void close(Connection connection, Statement statement) {
   
        //直接调用上面的方法
        close(connection, statement, null);
    }


    /**
     * 通用的增删改的方法
     * @param sql 要执行的SQL语句
     * @param params 替换占位符的真实地址,在方法内部是一个数组(从0开始)
     * @return 影响的行数
     */
    public static int update(String sql, Object... params) {
   
        Connection connection = null;
        PreparedStatement ps = null;

        int row = 0;  //影响的行数
        try {
   
            //1.创建连接对象
            connection = getConnection();
            //2.创建预编译的语句对象
            ps = connection.prepareStatement(sql);
            //2.5 得到参数元数据
            ParameterMetaData metaData = ps.getParameterMetaData();
            int count = metaData.getParameterCount();  //获取有几个参数
            //3.替换占位符为真实的值
            for (int i = 0; i < count; i++) {
   
                ps.setObject(i + 1, params[i]);  //一定是个对象类型
            }
            //4.执行SQL语句
            row = ps.executeUpdate();
        } catch (SQLException e) {
   
            e.printStackTrace();
        } finally {
   
            close(connection, ps);  //调用自己的方法
        }
        return row;
    }

    /**
     * 通用的查询方法
     * @param sql 要执行的SQL语句
     * @param clazz 要实例化的类型,如:Student.class, Employee.class
     * @param params 替换占位符的真实值
     * @return 封装好的集合对象
     */
    public static <T> List<T> query (String sql, Class<T> clazz, Object...params) {
   
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;

        List<T> list = new ArrayList<>();
        try {
   
            //1.创建连接对象
            connection = getConnection();
            //2. 创建预编译的语句对象
            ps = connection.prepareStatement(sql);
            //2.5 得到参数元数据
            ParameterMetaData metaData = ps.getParameterMetaData();
            int count = metaData.getParameterCount();  //获取有几个参数
            //3.替换占位符为真实的值
            for (int i = 0; i < count; i++) {
   
                ps.setObject(i + 1, params[i]);  //一定是个对象类型
            }
            //4.执行查询操作
            resultSet = ps.executeQuery();
            //5.遍历整个结果集,封装到集合中,每个元素是一个对象
            while(resultSet.next()) {
   
                //每条记录封装成一个对象,创建一个对象
                T obj = clazz.getConstructor().newInstance();
                //先得到实体类中有哪些属性
                Field[] fields = clazz.getDeclaredFields();  //得到所有成员变量,包含私有的
                //遍历每个成员变量,进行赋值
                for (Field field : fields) {
   
                    //私有的要暴力
                    field.setAccessible(true);
                    //列名=属性名
                    String name = field.getName();
                    //要赋值的对象,值
                    field.set(obj, resultSet.getObject(name));   //从结果集中获取数据
                }
                //6.添加到集合中
                list.add(obj);
            }
        }
        catch (Exception ex) {
   
            ex.printStackTrace();
        }
        finally {
   
            close(connection, ps, resultSet);
        }
        return list;
    }
}

package com.itheima.framework;

import com.itheima.entity.User;
import com.itheima.utils.JdbcUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * 模拟SqlSession类
 */
public class SqlSession {
   

    /**
     * 获取UserMapper的代理对象
     */
    public <T> T getMapper(Class<T> daoInterface) {
   
        /**
         * 生成T接口的代理对象
         * 参数1:类加载器
         * 参数2:所有被代理的接口数组,这里就是一个。创建一个匿名数组
         * new String[] {"a","b","c"}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值