MyBatis笔记(一)——入门与简单Mapper实现CRUD

MyBatis笔记(一)——入门与简单Mapper实现CRUD


参考: https://www.bilibili.com/video/BV1NE411Q7Nx

视频原作者CSDN: https://blog.csdn.net/qq_33369905

这篇是自己整理了一下,以便自己复习。

1.MyBatis简介

参考:MyBatis百度百科

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。

  • Mybatis官方中文文档​(​最好的MyBatis文档)⚡️ : http://www.mybatis.org/mybatis-3/zh/index.html
  • GitHub : https://github.com/mybatis/mybatis-3

2.导入依赖与Maven资源过滤

这个例子是一个只有MyBatis的maven工程,没有整合Spring或SpringBoot:

SpringBoot数据访问——整合MyBatis

maven工程依赖:

<?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-study</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>mabatis-01</module>
    </modules>

    <!--    导入依赖   -->
    <dependencies>

        <!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</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>

<!--    maven资源过滤 xml-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>

    </build>


</project>

3.MyBatis配置文件MyBatis-config.xml⚡️

  • 配置数据库连接信息:driver,url,username,password
  • 配置mapper.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"> 还可设置测试环境,生产环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://你的ip:3306/数据库名称?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="账号"/>
                <property name="password" value="密码"/>
            </dataSource>
        </environment>
    </environments>

<!--    每一个mapper都需要在配置文件中注册 mapper.xml  默认从resource-->
    <mappers>
   <!--   三种写法 类class 绝对地址url resource(一般用这个) -->
        <!-- 举例-->
        <!-- <mapper resource="com/piao/dao/UserMapper.xml"/>-->
    </mappers>

</configuration>

4.数据表与实体类

建表sql:

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `user`(`id`,`name`,`pwd`) values (1,'狂神','123456'),(2,'张三','abcdef'),(3,'李四','987654');

User.java(没用Lombok)

public class User {

    private int id;  //id
    private String name;   //姓名
    private String pwd;   //密码

    //构造,有参,无参
    //set/get
    //toString()
    public User() {
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}

5.获取SqlSession的工具类

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;

//SqlSessionFactory获取SqlSession
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    //静态代码块,初始时就执行
    static {
        try {
            //从配置文件读取配置,获取SqlSession对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //从SqlSessionFactory获取SqlSession连接
    public static SqlSession getSession(){
        return sqlSessionFactory.openSession();
    }

}

6.(CRUD⚡️)编写DAO接口类与对应的Mapper.xml

6.1 接口类的编写

UserMapper接口类,基本的增删改查接口:


import java.util.List;

//操作数据库的接口
public interface UserMapper {

    //查询所有User
    List<User> selectUser();

    //按照id查询User
    User selectUserById(int id);

    //插入一个用户 可传对象
    void insertUser(User user);

    //修改一个用户
    void updateUser(User user);

    //根据id删除一个用户
    void deleteUser(int id);

}
6.2 UserMapper.xml的编写

MyBatis的第一个最主要内容就是xml文件的编写

  • xml有mapper包裹,其namespace属性是规定命名空间,填写该xml对应的DAO接口类,及上述的UserMapper,需要填写全限定名(比如:com.piao.dao.UserMapper)

  • mapper里面写增删改查的标签 select ,insert,update,delete.都通过id属性指定该标签对应mapper接口类中的方法名称。比如第一个select标签中id="selectUser"即该标签对应UserMapper接口类中的selectUser方法

  • resultType 结果类型(将sql执行的结果自动封装成该类型)

  • parameterType 参数类型(基础数据类型或自定义类),在SQL中使用 **#{ }**传参数

<?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">

<!--namespace绑定一个对应的Mapper接口-->
<mapper namespace="com.piao.dao.UserMapper">

    <!-- 数据表名称user-->
    <!-- id对应 mapper接口的selectUser()方法  resultType:(全限定名)返回结果类型(返回一个) resultMap   -->
    <select id="selectUser" resultType="com.piao.pojo.User">
      select * from user;
    </select>

    <!--    parameterType参数类型-->
    <!--    传参方式: #{id}  id为selectUserById方法中的int类型参数id selectUserById(int id);-->
    <select id="selectUserById" parameterType="int" resultType="com.piao.pojo.User">
        select * from user where id = #{id};
    </select>

    <!--    插入一个用户 参数传来一个对象 可以直接从里面取属性的值-->
    <insert id="insertUser" parameterType="com.piao.pojo.User">
        insert into user(id,name,pwd) values (#{id},#{name},#{pwd});
    </insert>

    <!--    修改用户,同理-->
    <update id="updateUser" parameterType="com.piao.pojo.User">
        update user set name=#{name} ,pwd=#{pwd} where id=#{id};
    </update>

    <!--    parameterType="int"可省略  基本数据类型可省略-->
    <delete id="deleteUser" parameterType="int">
        delete from user where id =#{id};
    </delete>


</mapper>

7.junit测试上述mapper接口

junit最基本的操作:

@BeforeClass – 表示在类中的任意public static void方法执行之前执行
@AfterClass – 表示在类中的任意public static void方法执行之后执行
@Before – 表示在任意使用@Test注解标注的public void方法执行之前执行
@After – 表示在任意使用@Test注解标注的public void方法执行之后执行
@Test – 使用该注解标注的public void方法会表示为一个测试方法

增删改都需要提交数据库事务!否则操作不生效·

数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,
这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。
事务由事务开始与事务结束之间执行的全部数据库操作组成。

具体的测试代码,测试了userMapper接口中的所有方法:

package com.piao.dao;

import com.piao.pojo.User;
import com.piao.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

//测试
public class UserMapperTest {
    static SqlSession session;
    static UserMapper mapper;

    //测试前初始化SqlSession 与mapper
    @Before
    public void init() {
        session = MybatisUtils.getSession();//获取sqlsession
        //session.selectList("com.kuang.mapper.UserMapper.selectUser");//获取session中的mapper 方法一
        mapper = session.getMapper(UserMapper.class);//获取session中的mapper 方法二(一般用这个)
    }
    
    //测试后统一关闭SqlSession
    @After
    public void closeSqlSession() {
        //关闭sqlsession
        session.close();
    }

    //测试查询所有用户selectUser()
    @Test
    public void testSelectUser() {
        System.out.println("测试查询所有用户selectUser()");
        List<User> users = mapper.selectUser();
        for (User user : users) {
            System.out.println(user);
        }
        System.out.println();
    }

    //测试按照id查询用户selectUserById()
    @Test
    public void testSelectUserById() {
        System.out.println("测试按照id查询用户selectUserById()");
        User user = mapper.selectUserById(2);
        System.out.println(user);
        System.out.println();
    }

    //测试插入一个用户insertUser(User user)
    @Test
    public void testInsertUser() {
        System.out.println("测试插入一个用户insertUser(User user)");
        User user = new User(4, "王五", "2333");
        mapper.insertUser(user);



        session.commit();//提交事务  原生jdbc则需要开启事务执行sql后提交事务
        System.out.println("插入用户 " + user);
    }


    //测试修改一个用户updateUser(User user);
    @Test
    public void testUpdateUser(){
        System.out.println("测试修改一个用户updateUser(User user);");
//        name 王五-》王五五
        User user = new User(4, "王五五", "2333");
        mapper.updateUser(user);
        System.out.println("修改用户 " + user);
        session.commit();//提交事务
    }


    //测试根据id删除一个用户
    @Test
    public void testDeleteUser(){
        System.out.println("测试根据id删除一个用户");
        User user =mapper.selectUserById(4);
        System.out.println("删除用户 " + user);
        mapper.deleteUser(4);
        session.commit();//提交事务
    }


}

拓展1.Map传参

若实体类属性 或 数据库字段比较多时,可以考虑使用Map传参。

这是DAO到数据库这里使用map传参,而且是属性比较多的时候可以考虑使用。

不建议在Controller层中使用Map传参!不利于维护

coodesheep 谁要是再敢用Map传参,我过去就是一JIO

UserMapper接口

    //插入一个用户 可传对象
    void insertUser(User user);
   //笔记2
    //插入一个用户 使用Map传参
    void insertUserByMap(Map<String,Object> map);

UserMapper.xml

    <!--    插入一个用户 参数传来一个对象 可以直接从里面取属性的值-->
    <insert id="insertUser" parameterType="com.piao.pojo.User">
        insert into MyBatis.user(id,name,pwd) values (#{id},#{name},#{pwd});
    </insert>  
<!--    笔记二-->
    <!--    插入一个用户 参数传来一个Map 此处变为需要与map中的key一一对应-->
    <!--   好处:数据库字段多时,考虑使用map,因为无需实例化一个实体类 -->
    <insert id="insertUserByMap" parameterType="map">
        insert into MyBatis.user(id,name,pwd) values (#{userId},#{userName},#{userPassword});
    </insert>

测试:

//测试
public class UserMapperTest {
    static SqlSession session;
    static UserMapper mapper;
    //初始化SqlSession 与mapper
    @Before
    public void init() {
        session = MybatisUtils.getSession();//获取sqlsession
        mapper = session.getMapper(UserMapper.class);//获取session中的mapper 方法二(一般用这个)
    }
    //测试后统一关闭SqlSession
    @After
    public void closeSqlSession() {
        session.close();
    }  
//笔记2
    @Test
    public void testInsertUserByMap(){
        Map<String, Object> map = new HashMap<>();
        map.put("userId",5);
        map.put("userName","赵六");
        map.put("userPassword","13100");
        mapper.insertUserByMap(map);
        session.commit();//提交事务
    }

好处,举例说明:例如修改密码的场景,其实只需要传id和password就可以了,如果User这个实体类属性比较多,而且初始化时有的字段不能为空(比如使用了用于参数校验的@NotNull, @NotBlank, @NotEmpty ),这样就必须拿到这些属性值,而使用Map传参数就不需要。

拓展2.模糊查询 注意点(防止SQL注入的问题)

1.Java代码执行时,传递通配符 % %(推荐)

Java中
     List<User> userList = mapper.selectUserLike("%李%");

xml中
      select * from user where name like #{value}; 

2.在SQL拼接时使用通配符! 会引起sql注入

Java中
      List<User> userList = mapper.selectUserLike("李");
xml中    
      select * from user where name like "%"#{value}"%";

拓展3.参数传递注解@Param

用map也行

场景:根据 密码 和 名字 查询用户

1、在接口方法的参数前加 @Param属性

2、Sql语句编写的时候,直接取@Param中设置的值即可,不需要单独设置参数类型

@Param用于给方法参数起一个名字,需要注意:

  • 在方法只接受一个参数的情况下,可以不使用@Param。
  • 在方法接受多个参数的情况下,建议一定要使用@Param注解给参数命名。
  • 如果参数是 JavaBean , 则不能使用@Param。

接口定义:

User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);

xml配置

   <select id="selectUserByNP" resultType="com.piao.pojo.User">
     select * from user where name = #{username} and pwd = #{pwd}
   </select>

测试

    //拓展 多参数(用map也行)
    @Test
    public void testSelectUserByNP(){
        User user = mapper.selectUserByNP("张三", "abcdef");
        System.out.println(user);
    }

拓展4 #与$的区别

#与$的区别

在mybatis中使用#{}可以防止sql注入,提高系统安全性。

  • {}是预编译处理
  • ${}是字符串替换
  • #{ } 的作用主要是替换预编译语句(PrepareStatement)中的占位符 ? 【推荐使用】

    INSERT INTO user (name) VALUES (#{name});
    INSERT INTO user (name) VALUES (?);
    
  • ${ } 的作用是直接进行字符串替换

    INSERT INTO user (name) VALUES ('${name}');
    INSERT INTO user (name) VALUES ('kuangshen');
    

拓展5 自动提交事务

//SqlSessionFactory获取SqlSession
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    //静态代码块,初始时就执行
    static {
        try {
            //从配置文件读取配置,获取SqlSession对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //从SqlSessionFactory获取SqlSession连接
    public static SqlSession getSession(){
        //return sqlSessionFactory.openSession();//默认为flase,需要手动commit事务
        return sqlSessionFactory.openSession(true);//自动提交事务
    }

}

MyBatis笔记合集

MyBatis笔记(一)——入门与简单Mapper实现CRUD

MyBatis笔记(二)——配置(环境配置,别名优化,mapper映射器,属性 properties),生命周期和作用域

MyBatis笔记(三)——ResultMap结果集映射,日志,分页的多种实现方式

MyBatis笔记(四)——动态SQL元素(if,where,set,trim,choose,when,otherwise,foreach),SQL片段

MyBatis笔记(五)——一级缓存,二级缓存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值