MyBatis

这篇博客详细介绍了MyBatis的基本配置步骤,包括创建项目、导入依赖、配置核心文件,以及如何实现增删改查(CRUD)操作。此外,还讨论了使用Map作为参数、配置解析、类型别名、设置、映射器绑定和结果集映射。博主通过实际例子展示了动态SQL的使用,如if、choose、set和foreach,并讲解了如何抽取SQL片段以提高代码复用性。
摘要由CSDN通过智能技术生成

1、基本配置

思路:搭建环境—>导入mybatis—>编写代码—>测试

1、创建项目并删除src把项目当做父工程

在这里插入图片描述

2、导入依赖

<dependencies>
    <!-- mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>

    <!-- 单元测试依赖 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>

</dependencies>

3、配置mybatis核心配置文件

在resources文件夹下创建mybatis-config.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核心配置文件-->
<configuration>
<!--environments:环境,可配置多个环境;default="development":默认使用id="development"这个环境-->
    <environments default="development">
        <environment id="development">
        <!--transactionManager:事务管理方式,使用JDBC的事务管理-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="admin"/>
                <property name="password" value="admin"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

2、编写mybatis工具类
在Utils包下创建MybatisUtils工具类,用来获取SqlSession

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

    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(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }
}

4、编写代码

  • 实体类
package com.abner.pojo;

//实体类
public class User {

    private int id;
    private String name;
    private int age;
    private String sex;

    public User() {
    }

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

    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

  • Dao接口类
package com.abner.dao;

import com.abner.pojo.User;

import java.util.List;

public interface UserDao {

    List<User> getUserList();

}

  • 接口实现类由原来的UserDaoImpl转变为UserMapper.xml配置文件(放在dao包下,其他地方也可以)
<?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.abner.dao.UserDao">
    <select id="getUserList" resultType="com.abner.pojo.User">
      select * from user;
    </select>
</mapper>

我们的Dao类想要执行UserMapper.xml里面的SQL,必须用namespace来唯一定位,即把dao和配置文件绑定起来,其原理和我们之前用impl类实现对应接口的原理是一样的。
select标签中 id对应的是Dao(Mappetr)类中的方法名字(必须一样),和之前实现接口重写其方法是一样的。
resultType为返回的数据类型(Dao类中返回值类型或返回值类型中的泛型的类型),和我们之前在实现类中执行完SQl获取的的结果集返回一样
在这里插入图片描述

5、测试

Junit测试

package com.abner.dao;

import com.abner.pojo.User;
import com.abner.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserDaoTest {

    @Test
    public void test(){

        //1、获得SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //2、方式一:执行sql
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
            System.out.println(user.toString());
        }

        //关闭session
        sqlSession.close();

    }

}

测试成功
在这里插入图片描述

注意点:
在这里插入图片描述
这里的错误是指在Mapper在Mapper注册中心里面类型接口Dao是未知的
MapperRegistry(Mapper注册中心)是什么?
在这里插入图片描述

<!--每一个Mapper.xml都需要在MyBatis配置文件中注册-->
<mappers>
    <mapper resource="com/abner/dao/UserMapper.xml"/>
</mappers>

resource绑定mapper,需要使用路径,不能用com.xx.xx这种方式
还有其他方式的绑定

错误二,初始化错误,原因的找不到Mapper.xml,但是我们不是已经在核心配置文件中注册了吗?
在这里插入图片描述
在这里插入图片描述
我们把UserMapper.xml问价复制到生成的target目录下的dao包下发现可以执行成功。那不可能每次都复制过去吧?
在这里插入图片描述
解决办法是在pom.xml文件中添加一下内容

<!--在build中配置resource,来防止我们的资源导出失败问题-->
<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>

false老师那里是true,但是我这里是true还是报错,改成false就成功了

错误三:https://blog.csdn.net/L_it123/article/details/106845391

最基础的构建顺序
在这里插入图片描述

2、实现增删改查(CRUD)

在这里插入图片描述
namespace:要和Dao(Mapper)接口的报名一样

1、select

<select id="getUserList" resultType="com.abner.pojo.User" parameterType="xxx">
  select xxx from user where xxx=#(xxx);
</select>

选择,查询语句:

  • id:就是对应的namespace中的方法名
  • resultType:Sql语句执行的返回值
  • parameterType:Dao(Mapper)方法的参数类型

根据id查询用户
1、编写接口

//根据id查询用户
User getUserById(int id);

2、编写对应的mapper.xml中的sql语句

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

#{id}为接收方法的参数,里面的名应该和参数名一样

2、insert

1、编写接口

//insert一个用户
int insertUser(User user);

2、编写对应的mapper.xml中的sql语句

<!--对象中的属性,可以直接取出来-->
<insert id="insertUser" parameterType="com.abner.pojo.User">
    insert into user(id, name, age, sex) values (#{id} ,#{name},#{age},#{sex});
</insert>

我们方法的参数是User类型,在sql中只要接收的参数名和user的属性名一致,就可以接收到user里面对应属性的值。

3、update

1、编写接口

//修改用户
int updateUser(User user);

2、编写对应的mapper.xml中的sql语句

<update id="updateUser" parameterType="com.abner.pojo.User">
    update user set name=#{name},age=#{age},sex=#{sex} where id=#{id};
</update>

我们方法的参数是User类型,在sql中只要接收的参数名和user的属性名一致,就可以接收到user里面对应属性的值。

4、delete

1、编写接口

//删除用户
int deleteUser(int id);

2、编写对应的mapper.xml中的sql语句

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

注意我们在增、删、改的时候需要提交事务(sqlSession.commit()
测试类:

package com.abner.dao;

import com.abner.pojo.User;
import com.abner.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserDaoTest {

    @Test
    public void test(){
        //1、获得SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        try {
//        //2、方式一:执行sql
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = mapper.getUserList();
            //方式二:
            //List<User> userList = sqlSession.selectList("com.abner.dao.UserDao.getUserList");

            for (User user : userList) {
                System.out.println(user.toString());
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //关闭session
            sqlSession.close();
        }

    }

    @Test
    public void getUserById(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();

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

        User user = mapper.getUserById(5);
        System.out.println(user);

        sqlSession.close();

    }

    //增删改需要提交事务sqlSession.commit();
    @Test
    public void insertUser(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(8,"小巴",25,"女");
        int res = mapper.insertUser(user);
        if(res>0){
            System.out.println("插入成功!");
        }
        //提交事务
        sqlSession.commit();
        sqlSession.close();

    }

    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(9,"王九",30,"男");
        int res = mapper.updateUser(user);
        if(res>0){
            System.out.println("更新成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int res = mapper.deleteUser(10);
        if(res>0){
            System.out.println("删除成功!");
        }

        sqlSession.commit();

        sqlSession.close();
    }

}

3、万能的Map

//insert一个用户
int insertUser2(Map<String,Object> map);
<insert id="insertUser2" parameterType="map">
    insert into user(id, name, age, sex) values (#{id} ,#{name},#{age},#{sex});
</insert>
//增删改需要提交事务sqlSession.commit();
@Test
public void insertUser2() {

    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    Map<String,Object> map = new HashMap<String, Object>();

    map.put("id",10);
    map.put("name","小狗");
    map.put("age",14);
    map.put("sex","雄");

    int res = mapper.insertUser2(map);
    if (res > 0) {
        System.out.println("插入成功!");
    }
    //提交事务
    sqlSession.commit();
    sqlSession.close();

}

在这里插入图片描述
只要map中的key的值和sql中的获取参数的名字一样,就可以获取到map中对应key的value,所以我们想传什么字段就在map中put进去一个字段,而不用反复的修改实体类,所以说这是万能的map,很灵活。
在这里插入图片描述
Map传递参数,直接在sql中取出key即可!
对象传递参数,直接在sql中取出对象的属性即可!
只有一个基本类型的参数情况下,可以直接在Sql中取到

4、配置解析

1、核心配置文件

mybatis-config.xml(官方推荐名)
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

  • configuration(配置)
  • properties(属性)
  • settings(设置)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境配置)
    • environment(环境变量)
      • transactionManager(事务管理器)
      • dataSource(数据源)
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器)

2、引入外部配置文件(properties文件)

db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8
username=admin
password=admin

在mybatis-config.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>
    <!--引入properties文件用<properties>标签,
        标签之间有顺序
        properties->settings->typeAliases->typeHandlers->objectFactory->objectWrapperFactory->reflectorFactory->
        plugins->environments->databaseIdProvider->mappers
    -->
    <!--引入外部配置文件-->
    <properties resource="db.properties"/>

    <environments default="development">
        <environment id="development">
            <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>

<mappers>
    <mapper resource="com/abner/mybatis/dao/UserMap

per.xml"/>
    </mappers>
</configuration>

引入之后就可以用${属性}获取properties文件对应属性的值

在properties标签中可以直接增加属性

<properties resource="db.properties">
    <property name="username" value="admin"/>
    <property name="passwordd" value="admin"/>
</properties>

如果properties标签中的property的属性名和外部配置文件中的属性名相同,会优先使用外部配置文件的;

3、类型别名(typeAliases)

在核心配置文件中指定某个类的别名

    <!--给实体类型起别名-->
    <!--方式一-->
    <typeAliases>
        <typeAlias type="com.abner.mybatis.pojo.User" alias="User"/>
    </typeAliases>

    <!--方式二,扫描实体类所在的包,会使用实体类类名的首字母小写来作为它的别名(大写也行)-->
    <typeAliases>
        <package name="com.abner.mybatis.pojo"/>
    </typeAliases>

那么我们在mapper.xml文件中使用别名

<select id="getUserList" resultType="User">
    select * from user;
</select>

在实体类比较少的时候,推荐使用第一种
如果实体类比较多,建议第二种
第一种可以DIY,第二种则不行,如果非要改,需要在实体类上添加注解@Alias(“别名”)
在这里插入图片描述

4、设置(setting)

设置(settings)相关 => 查看帮助文档

  • 懒加载

  • 日志实现

  • 缓存开启关闭

一个配置完整的 settings 元素的示例如下:

<settings>
	 <setting name="cacheEnabled" value="true"/>
	 <setting name="lazyLoadingEnabled" value="true"/>
	 <setting name="multipleResultSetsEnabled" value="true"/>
	 <setting name="useColumnLabel" value="true"/>
	 <setting name="useGeneratedKeys" value="false"/>
	 <setting name="autoMappingBehavior" value="PARTIAL"/>
	 <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
	 <setting name="defaultExecutorType" value="SIMPLE"/>
	 <setting name="defaultStatementTimeout" value="25"/>
	 <setting name="defaultFetchSize" value="100"/>
	 <setting name="safeRowBoundsEnabled" value="false"/>
	 <setting name="mapUnderscoreToCamelCase" value="false"/>
	 <setting name="localCacheScope" value="SESSION"/>
	 <setting name="jdbcTypeForNull" value="OTHER"/>
	 <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

5、映射器mapper

MapperRegistry:注册绑定我们的Mapper文件:
方式一:使用mapper.xml注册绑定(推荐使用)

<!--每一个Mapper.xml都需要在MyBatis配置文件中注册-->
<mappers>
    <mapper resource="com/abner/mybatis/dao/UserMapper.xml"/>
</mappers>

方式二:使用class文件绑定注册

<!--
使用映射器接口实现类的完全限定类名
需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
    <mapper class="com.abner.mybatis.dao.UserMapper"/>
</mappers>

使用方式二的注意点:

  • 接口和他的Mapper.xml配置文件必须同名
  • 接口和他的Mapper.xml配置文件必须在同一个包下

方式三:使用扫描包注入绑定

<!--
将包内的映射器接口实现全部注册为映射器
但是需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
 <package name="com.abner.mybatis.dao"/>
</mappers>

注意点和方式二一样

6、结果集映射

如果我们实体类的属性名和数据库表中的字段名不一致的话,那么查询出来的结果会映射不到实体类上
在这里插入图片描述
那么我们就需要在mapper.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="com.abner.mybatis.dao.UserMappers">

    <!--结果集映射-->
    <resultMap id="UserMap" type="User">
        <!--column数据库中的字段名,property实体类中的属性名-->
        <result column="id" property="id"/>
        <result column="name" property="name" />
        <result column="age" property="age"/>
        <result column="sex" property="sexx"/>
    </resultMap>

    <select id="getUserById" resultMap="UserMap">
        select * from user where id=#{id};
    </select>

</mapper>

在这里插入图片描述

5、使用注解开发

在mybatis-config.xml文件中用接口注册mapper

    <mappers>
        <mapper class="com.abner.mybatis.dao.UserMapper"/>
    </mappers>

然后在接口的方法中使用@Select、@Insert、@Update、@Delete标签

package com.abner.mybatis.dao;

import com.abner.mybatis.pojo.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface UserMapper {

    @Select("select * from user")
    List<User> getUsers();

    @Select("select * from user where id = #{id}")
    User getUserById(@Param("id") int id);

    @Insert("insert into user(name,age,sex) values(#{name},#{age},#{sex}) ")
    int addUser(User user);

    @Update("update user set name = #{name},age=#{age},sex=#{sex} where id = #{id}")
    int updateUser(User user);

    @Delete("delete from user where id = #{id}")
    int deleteUserById(@Param("id") int id);
    

}



有参数的方法用@Paramb绑定参数,sql语句中获取的id就是@Param中的值绑定的,即#{}里面的id对应@Param()的id

注意:

  • 一定要把接口注册绑定到我们的核心配置文件中

6、 动态SQL

1、if

如果某个条件是第一个条件并且前面有and,where标签会把第一个条件的and去掉。

<!--动态Sql-->
<select id="queryBlogIF" parameterType="map" resultType="Blog">
    select * from blog
--          如果下面有如何条件的会自动增加where子句
    <where>
--          如果有传入title这个参数,就会怎sql后面拼接if里面语句
        <if test="title != null">
          title = #{title}
        </if>
--             如果有传入author这个参数,就会怎sql后面拼接if里面语句,如果没有传上面的title,会自动把and去掉
        <if test="author != null">
          and author = #{author}
        </if>
    </where>
</select>

2、 choose

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

<select id="queryBlogChoose" parameterType="map" resultType="Blog">
    select * from blog
    <where>
--             相当于switch case 语句,只要从上往下检查,只要碰到满足的条件的就结束,不在拼接后面的,如果都不满足,就拼接otherwise中的
        <choose>
            <when test="title != null">
                title = #{title}
            </when>
            <when test="author != null">
                and author = #{author}
            </when>
            <otherwise>
                and views = #{views}
            </otherwise>
        </choose>
    </where>
</select>

3、set

同理,上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词,我们怎么处理呢?

<update id="updateBlob" parameterType="map">
    update blog
--         set元素会动态前置SET关键字,同时也会删除无关的逗号
    <set>
        <if test="title != null">
            title = #{title},
        </if>
        <if test="author != null">
            author = #{author}
        </if>
    </set>
    where id = #{id}
</update>

所谓的动态SQL本质还是SQL语句,知识我们可以在SQL层面,去执行一个逻辑代码

4、foreach

将数据库中前三个数据的id修改为1,2,3;

需求:我们需要查询 blog 表中 id 分别为1,2,3的博客信息

1、编写接口

List<Blog> queryBlogForeach(Map map);

2、编写SQL语句

<select id="queryBlogForeach" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!--
       collection:指定输入对象中的集合属性
       item:每次遍历生成的对象
       open:开始遍历时的拼接字符串
       close:结束时拼接的字符串
       separator:遍历对象之间需要拼接的字符串
       select * from blog where 1=1 and (id=1 or id=2 or id=3)
     -->
       <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
          id=#{id}
       </foreach>
   </where>
</select>

3、测试

@Test
public void testQueryBlogForeach(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   HashMap map = new HashMap();
   List<Integer> ids = new ArrayList<Integer>();
   ids.add(1);
   ids.add(2);
   ids.add(3);
   map.put("ids",ids);

   List<Blog> blogs = mapper.queryBlogForeach(map);

   System.out.println(blogs);

   session.close();
}

5、抽取SQL片段

有时候我们可能会将一些功能的部分抽取出来,方便复用
1、使用SQL标签抽取公共的部分

<!--把公共的动态SQL片段提取出来,在需要用到的地方用include标签引用-->
<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

2、在需要使用的地方使用include标签引用即可

<!--动态Sql-->
<select id="queryBlogIF" parameterType="map" resultType="Blog">
    select * from blog
    <where>
      <include refid="if-title-author"></include>
    </where>
</select>

注意事项:

  • 最好基于单表来定义SQL片段
  • 不要存在where标签
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值