Mybatis02

Mybatis学习的第二天,有Mybatis核心配置文件、测试的准备、Mybatis工具类的封装、易错点。

Mybatis学习02

1、Mybatis核心配置文件

  • XML 配置文件中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。

  • 官方推荐XML配置文件命名为:mybatis-config.xml

    XML文件放置的路径为:main/resources

    <?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>
        //默认的环境id为“development”
      <environments default="development">
          //一个环境的配置
        <environment id="development">
            //事务管理器类型为JDBC,还有一个MANAGED,但是几乎不用了
          <transactionManager type="JDBC"/>
            //数据源为一个池子
          <dataSource type="POOLED">
              //连接数据库的各种配置
            <property name="driver" value="driver"/>
            <property name="url" value="{url"/>
            <property name="username" value="username"/>
            <property name="password" value="password"/>
          </dataSource>
        </environment>
      </environments>
    </configuration>
    

2、测试的准备

  • Jave Bean

    实体类的创建和之前的创建方式一样。

    package com.neversettle.domain;
    
    public class User {
        private int id;
        private String username;
        private String birthday;
        private String sex;
        private String address;
    
        public User() {
        }
    
        public User(int id, String username, String birthday, String sex, String address) {
            this.id = id;
            this.username = username;
            this.birthday = birthday;
            this.sex = sex;
            this.address = address;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getBirthday() {
            return birthday;
        }
    
        public void setBirthday(String birthday) {
            this.birthday = birthday;
        }
    
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", birthday='" + birthday + '\'' +
                    ", sex=" + sex +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
    
  • 实体类的持久化操作,也就是UserDao,但是Mybatis官方使用的是Mapper,所以此处命名为UserMapper(后期优化Mybatis也需要此种规范命名)

    package com.neversettle.dao;
    
    import com.neversettle.domain.User;
    
    import java.util.List;
    
    public interface UserMapper {
        //获取全部用户信息
        List<User> getUserList();
    
        //根据ID获取用户信息
        User getUserById(int id);
    
        //新增一个用户
        void addUser(User user);
    
        //修改用户信息
        int updateUser(User user);
    
        //删除一个用户
        int deleteUser(int id);
    }
    
    

    这里只需要写出其接口即可,具体的实现是在XML中执行的。

  • UserMapper的具体实现,需要在其UserMapper的同一目录下建一个名为 UserMapper.xml 文件,文件中写出其具体实现。

    官方文档: 事实上 MyBatis 提供的全部特性都可以利用基于 XML 的映射语言来实现,这使得 MyBatis 在过去的数年间得以流行。

    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="org.mybatis.example.BlogMapper">
      <select id="selectBlog" resultType="Blog">
        select * from Blog where id = #{id}
      </select>
    </mapper>
    
    • mapper中有着CRUD的各个标签,相应的SQL语句都在对应的标签中书写。
    • select等标签中id对应的是接口中的方法名,该标签就是接口中方法的具体实现。
    • resultType是返回值类型,如返回的类型是具体的实体类,则写出具体的实体类,注意此时需要写出完整的地址,如之前的javabean中实体类的,则需写出实体类所在包名+实体类名,如com.neversettle.domain (后期可使用注解优化)
    • 如果需要传参数,则需写出传入的参数类型,向SQL语句中插入时使用 #{} 花括号中写出参数,如果传入的参数是一个实体类,则可以直接写出实体类的属性。如User实体类中有id属性,则可直接写出 #{id} 。

    而我实际的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">
    
    <!--namespace绑定一个指定的Dao/Mapper接口-->
    <mapper namespace="com.neversettle.dao.UserMapper">
    <!--    查询语句-->
        <select id="getUserList" resultType="User">
            select * from user
        </select>
    
    <!--    根据ID查询用户-->
        <select id="getUserById" parameterType="int" resultType="User">
            select * from user where id = #{id}
        </select>
    
    <!--    新增加一个用户-->
        <insert id="addUser" parameterType="User">
            insert into user values(#{id},#{username},#{birthday},#{sex},#{address})
        </insert>
        
    <!--    修改用户信息-->
        <update id="updateUser" parameterType="User">
            update user set username = #{username} where id = #{id};
        </update>
    
    <!--    删除用户信息-->
        <delete id="deleteUser" parameterType="int">
            delete from user where id = #{id}
        </delete>
    
    </mapper>
    
  • 在Test中写测试代码

    • 需要获得类似之前的connection的连接,在Mybatis中是SqlSession,而Mybatis中使用的是工厂模式(还未学习,暂且这样理解),SqlSession是从工厂中获取,而工厂就相当于一个池子,可以产生多个连接,官方给出的工厂获取代码如下:

      String resource = "org/mybatis/example/mybatis-config.xml";
      InputStream inputStream = Resources.getResourceAsStream(resource);
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      

      而获取一个SqlSession的代码是:

      SqlSession sqlSession = sqlSessionFactory.openSession();
      

      接下来就可以来实现接口了,具体应该使用:

      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      

      然后便可使用mapper来执行具体的方法,如:

      User userById = mapper.getUserById(43);
      
    • 而我的具体代码为(封装了Mybatis获取SqlSession的工具类):

      package com.neversettle.dao;
      
      import com.neversettle.domain.User;
      import com.neversettle.utils.MybatisUtils;
      import org.apache.ibatis.session.SqlSession;
      import org.junit.Test;
      
      import java.util.List;
      
      public class UserMapperTest {
      
          @Test
          public void test(){
              //1.获取SqlSession对象
              SqlSession sqlSession = MybatisUtils.getSqlSession();
      
      
              //2.执行sql(第一种)
              UserMapper userDao = sqlSession.getMapper(UserMapper.class);
              List<User> userList = userDao.getUserList();
              for (User user : userList) {
                  System.out.println(user.toString());
              }
      
      
              //3.关闭SqlSession
              sqlSession.close();
          }
      
      
          @Test
          public void getUserById(){
              //1.获取sqlsession
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              //2.执行sql
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
              User userById = mapper.getUserById(43);
              System.out.println(userById);
              //3.关闭
              sqlSession.close();
          }
      
          @Test
          public void addUser(){
              //1.获取执行的sqlsession
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              //2.执行
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
              mapper.addUser(new User(50,"张三","2020-01-18","男","河北省石家庄市"));
              //3.关闭
              sqlSession.commit();
              sqlSession.close();
          }
      
          @Test
          public void updateUser(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
              mapper.updateUser(new User(50,"123","","",""));
              sqlSession.commit();
              sqlSession.close();
          }
      
          @Test
          public void deleteUser(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
              mapper.deleteUser(50);
              sqlSession.commit();
              sqlSession.close();
          }
      }
      

3、Mybaits工具类的封装

类似之前的JDBCUtils一样,Mybatis有些步骤也是重复的,所以可以封装成一个工具类:

package com.neversettle.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;

public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        //获取sqlsessionfactory对象
        InputStream inputStream = null;
        try {
            String resource = "mybatis-config.xml";
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
    // SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
    // 你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
    public static SqlSession getSqlSession(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }
}

4、易错点

  • 首先是UserMapper.xml,每一个mapper都需要在Mybatis的核心配置文件中注册,之前写核心配置文件时没有我们这次使用的Mapper,所以肯定会出现mapper未注册的错误,更改后的Mybatis的核心配置文件:

    <?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/mybatis?useUnicode=ture&amp;characterEncoding=UTF-8&amp;serverTimezone=GMT%2B8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="newpassword"/>
                </dataSource>
            </environment>
        </environments>
    
        <!--    每一个Mapper.xml都需要注册-->
        <mappers>
            <mapper resource="com/neversettle/dao/UserMapper.xml"/>
        </mappers>
    
    </configuration>
    
  • 在执行增删改操作时,都需要提交事务,这和之前学习的不一样,之前学习的还需要自己开启事务然后再提交事务,这里貌似已经自动开启事务了,所以在执行完增删改操作后都需要提交事务,代码为:

     sqlSession.commit();
    
  • 第一次运行时,出现了 “ 1 字节的 UTF-8 序列的字节 1 无效” ,这是编码造成的问题,将IDEA的编码改为UTF-8,然后删掉 XML文件,再重写一个即可。

posted @ 2020-03-08 11:25  Nevesettle  阅读(138)  评论(0编辑  收藏  举报