Mybatis增删改查入门

一、开发环境搭建

1、项目使用maven构建,在pom.xml中引入以下依赖

<dependency>
  <groupId>org.mybatisgroupId>
  <artifactId>mybatisartifactId>
  <version>3.4.0version>
dependency>

<dependency>
   <groupId>mysqlgroupId>
   <artifactId>mysql-connector-javaartifactId>
   <version>5.1.36version>
 dependency>

<dependency>
  <groupId>junitgroupId>
  <artifactId>junitartifactId>
  <version>4.11version>
  
  <scope>testscope>
dependency>

mybatis在工作过程中,依赖数据源(DataSource),由于mybatis自带了几个简单的DataSource实现,这里我们直接使用mybatis自带的即可,不需要引入其他数据源的依赖。

2、创建user数据表

数据库使用MySql

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL COMMENT 'ID',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '姓名',
  `age` int(11) NULL DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
3、创建Java类User,与user表对应
public class User {
    private Integer id;
    private String name;
    private Integer age;

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;

    }

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

二、基于XML的使用方式

1、全局配置文件

全局配置文件通常命名为mybatis-config.xml,需要配置DataSource数据库连接,DataSource是全局唯一的。

在classpath下新建配置文件:mybatis-config.xml,一般是在resources目录下。





<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="MANAGED"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/java_test"/>
                
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            dataSource>
        environment>
    environments>
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    mappers>
configuration>
mappers元素

表示映射文件列表,前面提到通常我们针对数据库中每张表,都会建立一个映射文件。而在mappers元素中,就通过mapper元素,列出了所有配置文件的路径。

resource属性:表示映射文件位于classpath下。例如上面的配置中就表示在classpath的mappers目录下,有一个UserMapper.xml映射文件。

2、映射文件

通常一个表对映一个映射文件,通常一个项目会有很多个,命名规则一般是"类名+Mapper.xml",例如我们操作User类,其映射文件名字是UserMapper.xml,表示是User类的映射文件。

在classpath下创建目录mappers,并新建UserMapper.xml映射文件,一般是在resources目录下。



<mapper namespace="com.wip.mapper.UserMapper">

    
    <select id="findUserList" resultType="com.wip.model.User">
        SELECT
          *
        FROM
          <include refid="BASE_TABLE"/>
    select>

    
    <insert id="insert" parameterType="com.wip.model.User">
        INSERT INTO user
        (
            id,
            name,
            age
        )
        VALUES
        (
            #{id},
            #{name},
            #{age}
        )
    insert>

    
    <select id="findById" parameterType="int" resultType="com.wip.model.User">
        SELECT
          *
        FROM
          user
        WHERE
        id = #{id}
    select>

    
    <update id="updateById" parameterType="com.wip.model.User">
        UPDATE
          user
        SET
          name = #{name},
          age = #{age}
        WHERE
          id = #{id}
    update>

    
    <delete id="deleteById" parameterType="int">
        DELETE FROM
          user
        WHERE
          id = #{id}
    delete>

mapper>

说明:

mapper元素

xml映射文件的根元素。namespace属性表示命名空间,不同的xml映射文件namespace必须不同。原因在于mybatis使用namespace.id的方式来唯一定位一个sql,id指的是元素中内部包含对的insert、select、update、delete子元素中的id属性。
insert、select、delete、update元素:
这四个元素都是mapper文件中表示增删改查操作的子元素,每个子元素都可以配置多个,例如这里配置了两个select元素,我们将sql直接写在这些子元素的内部。每个元素都有一个id属性,通过namespace.id唯一定位这个sql。

正向映射:

正向映射通过parameterType属性指定,如insert和update元素,parameterType属性值为com.tianshouzhi.mybatis.quickstart.User,这是一个java对象。mybatis会自动帮我们将java对象的值取出来,来替换sql中的变量。例如insert和update中的#{name}和#{age}就分别会被User对象的name和age属性值替换,即mybatis会调用user.getName()来替换#{name},调用user.getAge()来替换#{age}。
不过我们还看到了,delete和select元素也配置了parameterType属性,这是因为在删除和查询的时候,我们也是需要指定条件的。这两个元素指定parameterType类型都是int,对应java的包装数据类型Integer。

反射映射:

反向映射通过resultType或者resultMap属性指定,这两个属性只能出现在元素配置的resultType属性值也是com.tianshouzhi.mybatis.quickstart.User,表示将数据库结果封装到这个类中。
resultType这种反向映射关系是基于数据库表字段与User类属性是完全对应的。例如对于数据库id、name、age字段,会自动调用User类的、setId、setName、setAge方法进行设置。如果表字段与实体属性不能一一对应的话,如数据库表字段为username,但是java类中定义的属性为name,则无法进行映射。

三、SqlSessionFactory&SqlSession介绍

在使用mybatis时,我们需要创建一个SqlSessionFactory对象,然后通过SqlSessionFactory来创建SqlSession,通过SqlSession提供的api支执行sql。

1、SqlSessionFactory

顾名思义,是创建SqlSession实例的工厂类。SqlSessionFactory,某种程度上可以认为其是在数据源(Datasouce)的基础上做的一层封装,因此在整个程序中,最好只保存一个SqlSessionFactory实例。
在mybatis中,我们通过SqlSessionFactory的openSession方法来获取SqlSession对象来操作数据库。
mybatis提供了一个SqlSessionFactoryBuilder对象,用于读取mybatis配置文件,创建SqlSessionFactory实例。以下代码演示了如何通过配置文件创建一个SqlSessionFactory实例。

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2、SqlSession

SqlSession可以认为是在数据库连接(Connection)的基础上做的一层封装。其提供我们操作数据库相关的API,一个SqlSession实例从创建到销毁整个过程中执行的所有sql,都是通过同一个Connection对象进行。

SqlSession中,为我们在xml映射文件中配置的元素对应的相关方法 <T> T selectOne(String statement); <T> T selectOne(String statement, Object parameter); <E> List<E> selectList(String statement); <E> List<E> selectList(String statement, Object parameter); <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds); <K, V> Map<K, V> selectMap(String statement, String mapKey); <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey); <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds); <T> Cursor<T> selectCursor(String statement); <T> Cursor<T> selectCursor(String statement, Object parameter); <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds); void select(String statement, Object parameter, ResultHandler handler); void select(String statement, ResultHandler handler); void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler); //元素对应的相关方法 int insert(String statement); int insert(String statement, Object parameter); //元素对应的相关方法 int update(String statement); int update(String statement, Object parameter); //元素对应的相关方法 int delete(String statement); int delete(String statement, Object parameter); //事务操作相关方法 void commit(); void commit(boolean force); void rollback(); void rollback(boolean force); //其他方法 List<BatchResult> flushStatements(); @Override void close(); void clearCache(); Configuration getConfiguration(); <T> T getMapper(Class<T> type); Connection getConnection(); }

四、测试

1、基于SqlSession测试

测试基于junit框架编写

public class QuickStartBasedSqlSession {

    // sql会话工厂
    public static SqlSessionFactory sqlSessionFactory;
    // mapper命名空间
    public static String namespace = "com.wip.mapper.UserMapper";
    // 会话
    public SqlSession sqlSession;

    //通过SqlSessionFactoryBuilder构造SqlSessionFactory实例
    @BeforeClass
    public static void testBefore() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    // 每个单元测试方法(添加@Test注解的方法)在执行前,此方法都会被juint框架回调,创建一个新的SqlSession实例
    @Before
    public void before() {
        sqlSession = sqlSessionFactory.openSession();
    }

    // 测试添加,调用sqlSession的insert方法
    @Test
    public void testInsert() {
        User user1 = new User();
        user1.setId(1);
        user1.setName("Kyrie");
        user1.setAge(20);
        User user2 = new User();
        user2.setId(2);
        user2.setName("Array");
        user2.setAge(22);
        String statement = namespace + ".insert";
        sqlSession.insert(statement, user1);
        sqlSession.insert(statement,user2);
    }

    // 测试查询单条记录,调用sqlSession的selectOne方法
    @Test
    public void testSelectOne() {
        User user = sqlSession.selectOne(namespace + ".findById",1);
        assert user != null;
        System.out.println("User: " + user);
    }
    // 测试查询多条记录,并将结果封装到一个List中,调用sqlSession的selectList方法
    @Test
    public void testSelectList() {
        List users = sqlSession.selectList(namespace + ".findUserList");
        assert  users != null;
        System.out.println("userList: " + users);
    }

    // 测试查询多条记录,并将结果封装到一个Map中,调用sqlSession的selectMap方法
    @Test
    public void testSelectMap() {
        Map userMap = sqlSession.selectMap(namespace + ".findUserList","id");
        System.out.println("userMap: " + userMap);
    }

    // 测试更新,调用sqlSession的update方法
    @Test
    public void testUpadte() {
        User user = sqlSession.selectOne(namespace + ".findById",1);
        assert user != null;
        user.setName("KyrieCao");
        user.setAge(20);
        int updateCount = sqlSession.update(namespace +".updateById", user);
        System.out.println("受影响的记录条数: " + updateCount);
    }

    // 测试删除,调用sqlSession的delete方法
    @Test
    public void testDelete() {
        int deleteCount = sqlSession.delete(namespace + ".deleteById",6);
        System.out.println("删除操作受影响的条数:" + deleteCount);
    }

    // 每个单元测试方法(添加@Test注解的方法)在执行后,此方法都会被juint框架回调,关闭SqlSession实例
    @After
    public void after() {
        sqlSession.close();
    }

}
  • 1、执行testInsert方法后,控制台输出
[com.wip.mapper.UserMapper.insert] - ==>  Preparing: INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? ) 
[com.wip.mapper.UserMapper.insert] - ==> Parameters: 1(Integer), Kyrie(String), 20(Integer)
[com.wip.mapper.UserMapper.insert] - <==    Updates: 1
[com.wip.mapper.UserMapper.insert] - ==>  Preparing: INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? ) 
[com.wip.mapper.UserMapper.insert] - ==> Parameters: 2(Integer), Array(String), 22(Integer)
[com.wip.mapper.UserMapper.insert] - <==    Updates: 1
  • 2、执行testSelectOne方法后,控制台输出
[com.wip.mapper.UserMapper.findById] - ==>  Preparing: SELECT * FROM user WHERE id = ? 
[com.wip.mapper.UserMapper.findById] - ==> Parameters: 1(Integer)
[com.wip.mapper.UserMapper.findById] - <==      Total: 1
User: User{id=1, name='Kyrie', age=20}
  • 执行testSelectList方法后,控制台输出
[com.wip.mapper.UserMapper.findUserList] - ==>  Preparing: SELECT * FROM user 
[com.wip.mapper.UserMapper.findUserList] - ==> Parameters: 
[com.wip.mapper.UserMapper.findUserList] - <==      Total: 2
userList: [User{id=1, name='Kyrie', age=20}, User{id=2, name='Array', age=22}]
  • 4、执行testSelectMap方法后,控制输出
[com.wip.mapper.UserMapper.findUserList] - ==>  Preparing: SELECT * FROM user 
[com.wip.mapper.UserMapper.findUserList] - ==> Parameters: 
[com.wip.mapper.UserMapper.findUserList] - <==      Total: 2
userMap: {1=User{id=1, name='Kyrie', age=20}, 2=User{id=2, name='Array', age=22}}
  • 4、执行testUpadte方法后,控制台输出
[com.wip.mapper.UserMapper.findById] - ==>  Preparing: SELECT * FROM user WHERE id = ? 
[com.wip.mapper.UserMapper.findById] - ==> Parameters: 1(Integer)
[com.wip.mapper.UserMapper.findById] - <==      Total: 1
[com.wip.mapper.UserMapper.updateById] - ==>  Preparing: UPDATE user SET name = ?, age = ? WHERE id = ? 
[com.wip.mapper.UserMapper.updateById] - ==> Parameters: KyrieCao(String), 20(Integer), 1(Integer)
[com.wip.mapper.UserMapper.updateById] - <==    Updates: 1
受影响的记录条数: 1
  • 5、执行testDelete方法后,控制台输出
[com.wip.mapper.UserMapper.deleteById] - ==>  Preparing: DELETE FROM user WHERE id = ? 
[com.wip.mapper.UserMapper.deleteById] - ==> Parameters: 6(Integer)
[com.wip.mapper.UserMapper.deleteById] - <==    Updates: 0
删除操作受影响的条数:0

对于直接使用SqlSession可以帮助我们理解mybatis的内部工作原理,但是在实际开发中,直接使用SqlSession的情况越来越少,除非是老项目。

2、基于Mapper接口测试

测试基于junit框架编写

import com.wip.model.User;
import java.util.List;
public interface UserMapper {

    /**
     * 查询所有记录
     * @return
     */
    List findUserList();

    /**
     * 插入数据
     * @param user
     * @return
     */
    int insert(User user);

    /**
     * 通过ID删除一条记录
     * @param id
     * @return
     */
    int deleteById(int id);

    /**
     * 通过ID更新一条记录
     * @param user
     * @return
     */
    int updateById(User user);

    /**
     * 通过ID查找一条记录
     * @param id
     * @return
     */
    User findById(int id);
}

通过观察会发现UserMapper接口的全路径com.wip.mapper.UserMapper,与UserMapper.xml中的namespace属性的值完全相同。

在UserMapper.xml中定义的各个元素元素。

五、总结

1、通过xml映射文件,配置元素id属性值相匹配。

2、通过注解映射,在Mapper接口的相应方法上添加@Insert、@Update、@Delete、@Select注解。

总的来说,直接使用SqlSession是最基础的使用方式,可以帮助我们了解mybatis内部的核心工作流程,目前使用xml映射文件+Mapper接口的方式使用最多,建议开发中使用这种方式。

你可能感兴趣的:(Mybatis)