项目代码

分割线

借物表

在此文章记录了: 😍Weidows-の成长路线#mybatis


简介

MyBatis 是优秀的持久层框架,简单来说就是方便存-取数据的工具.

持久层: Dao 层、Service 层、Controller 层

分割线

Hello-MyBatis

环境配置

  • 用 Maven 创建空项目,导入依赖&设置 Maven 过滤器:

    <!--导入依赖-->
    <dependencies>
    <!--mysqlq驱动-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.12</version>
    </dependency>
    <!--mybatis-->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.4</version>
    </dependency>
    <!--junit-->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    </dependency>
    </dependencies>

    <!--Mapper资源导出,不设置的话会报错-->
    <build>
    <resources>
    <resource>
    <directory>src/main/resources</directory>
    <includes>
    <include>**/*.properties</include>
    <include>**/*.xml</include>
    </includes>
    <filtering>true</filtering>
    </resource>
    <resource>
    <directory>src/main/java</directory>
    <includes>
    <include>**/*.properties</include>
    <include>**/*.xml</include>
    </includes>
    <filtering>true</filtering>
    </resource>
    </resources>
    </build>
  • 然后创建空的子模块,子模块中开发就不需要再导入依赖了,MyBatis 需要添加一个配置文件: src/main/resources/MyBatis-config.xml

    • 后面每增加一个 Mapper.xml,都需要在这里面添加 Mapper 映射;后面会提到.
    <?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核心配置文件-->
    <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/mybatis?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
    </dataSource>
    </environment>
    </environments>
    </configuration>

数据库

  • 初始化数据库和 pojo

    create schema User;


    create table User
    (
    id int not null,
    name varchar(30) default null null,
    pwd varchar(30) default null null,
    constraint User_pk
    primary key (id)
    ) ENGINE = INNODB
    DEFAULT CHARACTER SET = utf8;


    insert into User(id, name, pwd)
    values (1, '张三', 123456),
    (2, '李四', 123456),
    (3, '王五', 123456),
    (4, '赵六', 123456)

    • src/main/java/pojo/User.java

      package pojo;

      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
      private int id;
      private String name;
      private String pwd;
      }

工具类

src/main/java/utils/MyBatisUtils.java

package utils;

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 = null;

static {
try {
//使用Mybatis第一步 :获取sqlSessionFactory对象
String resource = "MyBatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例.
* SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
*/
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}

Dao

  • dao 中编写接口和绑定 Mapper.xml

    https://github.com/Weidows/Java/blob/master/MyBatis/1-hello-MyBatis/src/main/java/dao

    • 这里的 xml 配置绑定好接口,就可以让 MyBatis 负责 SQL 代码了,避免了 dao 层中 JDBC 代码过于繁杂和重复的问题

      <?xml version="1.0" encoding="UTF8" ?>
      <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

      <!--namespace=绑定一个指定的Dao/Mapper接口-->
      <mapper namespace="dao.UserMapper">
      <!--这里id就是方法名,相当于实现方法-->
      <select id="getUserList" resultType="pojo.User">
      select *
      from User
      </select>
      </mapper>
  • Mapper.xml 绑定的是与之对应的接口,然后需要在 MyBatis-config.xml中绑定需要的 Mapper.xml

    绑定关系: UserMapper.java -> UserMapper.xml -> MyBatis-config.xml

    添加绑定如下:

    <?xml version="1.0" encoding="UTF8" ?>
    <!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <!--configuration核心配置文件-->
    <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/mybatis?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
    </dataSource>
    </environment>
    </environments>

    <!--绑定Mapper.xml-->
    <mappers>
    <mapper resource="dao/UserMapper.xml"/>
    </mappers>
    </configuration>


测试

  • 注意 test 中层级与 main 中层级一一对应

    20210504111311
    package dao;

    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    import pojo.User;
    import utils.MyBatisUtils;

    import java.util.List;

    public class UserMapperTest {
    @Test
    public void test() {
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //2.执行SQL
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList = userMapper.getUserList();
    for (User user : userList) {
    System.out.println(user);
    }
    //关闭sqlSession
    sqlSession.close();
    }

    @Test
    public void test1() {
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //2.执行SQL
    List<User> userList = sqlSession.selectList("dao.UserMapper.getUserList");
    for (User user : userList) {
    System.out.println(user);
    }
    //关闭sqlSession
    sqlSession.close();
    }
    }
  • 排错:

    • org.apache.ibatis.binding.BindingException: Type interface dao.UserDao is not known to the MapperRegistry.

      这是因为 Mapper.xml 资源没有被 Maven 导出,所以找不到资源,解决办法:资源导出

    • 1字节的UTF-8序列的字节1无效的问题处理

      这个问题格外 dan 疼,把下面的 UTF-8 改为 UTF8 试试…

      <?xml version="1.0" encoding="UTF-8" ?>

分割线

开始 CRUD

  • 完善 CRUD 只需要修改下面三个文件:

  • src/main/java/dao/UserMapper.java

    package dao;

    import pojo.User;

    import java.util.List;

    public interface UserMapper {
    List<User> getUserList();

    User getUserById(int id);

    int addUser(User user);

    int updateUser(User user);

    int deleteUser(int id);
    }

  • src/main/java/dao/UserMapper.xml

    <?xml version="1.0" encoding="UTF8" ?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    <!--namespace=绑定一个指定的Dao/Mapper接口-->
    <mapper namespace="dao.UserMapper">
    <!--这里id就是方法名,相当于实现方法-->
    <select id="getUserList" resultType="pojo.User">
    select *
    from User
    </select>

    <select id="getUserById" resultType="pojo.User" parameterType="int">
    select *
    from mybatis.user
    where id = #{id}
    </select>

    <insert id="addUser" parameterType="pojo.User">
    insert into mybatis.user(id, name, pwd)
    values (#{id}, #{name}, #{pwd})
    ## 对象中的属性可以被直接取出来(这里取得可以是传入的参数,也可以是传入对象的属性)
    </insert>

    <update id="updateUser" parameterType="pojo.User">
    update mybatis.user
    set name =#{name},
    pwd=#{pwd}
    where id = #{id}
    </update>

    <delete id="deleteUser" parameterType="int">
    delete
    from mybatis.user
    where id = #{id}
    </delete>
    </mapper>

  • src/test/java/dao/UserMapperTest.java

    package dao;

    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    import pojo.User;
    import utils.MyBatisUtils;

    import java.util.List;

    public class UserMapperTest {
    @Test
    public void test() {
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //2.执行SQL
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList = userMapper.getUserList();
    for (User user : userList) {
    System.out.println(user);
    }
    //关闭sqlSession
    sqlSession.close();
    }

    @Test
    public void test1() {
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //2.执行SQL
    List<User> userList = sqlSession.selectList("dao.UserMapper.getUserList");
    for (User user : userList) {
    System.out.println(user);
    }
    //关闭sqlSession
    sqlSession.close();
    }

    @Test
    public void getUserById() {
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(mapper.getUserById(3));
    sqlSession.close();
    }

    @Test
    public void addUser() {
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    int i = mapper.addUser(new User(5, "五号", "123456"));
    if (i > 0) {
    //注意 增删改 需要提交事务
    sqlSession.commit();
    }
    sqlSession.close();
    }

    @Test
    public void updateUser() {
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    int i = mapper.updateUser(new User(5, "⑤号", "654321"));
    if (i > 0) {
    sqlSession.commit();
    }
    sqlSession.close();
    }

    @Test
    public void deleteUser() {
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    int i = mapper.deleteUser(5);
    if (i > 0) {
    sqlSession.commit();
    }
    sqlSession.close();
    }

    }

分割线

通过 Map 优化

//用Map插入用户
int addUser2(Map<String, Object> map);
<!--通过USer传参的话,必须用User的属性名取出; 而通过map传参的话,属性名可以任意-->
<insert id="addUser2" parameterType="Map">
insert into mybatis.user(id, name, pwd)
values (#{userid}, #{username}, #{userpassword})
</insert>
@Test
public void addUser2() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

HashMap<String, Object> map = new HashMap<>();
map.put("userid", 6);
map.put("username", "王虎");
map.put("userpassword", 789);

int i = mapper.addUser2(map);
if (i > 0) sqlSession.commit();
sqlSession.close();
}