MyBatis:概念简章

1. hello world

配置文件:
 mybatis-config.xml(核心配置文件,用于配置连接的数据库信息)(一般一个)
 XxxMapper.xml 该文件用于操作表(执行sql语句)(一张表一个)
细节:
 执行的sql语句";"可以省略
 一般有resource这个单词都会从类的根路径开始扫描文件
  1. 配置mybatis-config.xml文件
  2. 配置配置xxxMapper.xml文件
  3. 对数据库进行CRUD操作 
<?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/study"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!--路径映射,要操作的表-->
    <mappers>
        <mapper resource="mapper/EmployeeMapper.xml"/>
    </mappers>
</configuration>
<?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">
<!--要进行CURD操作的表-->
<mapper namespace="EmployeeMapper">
    <!--<select id="selectUser" resultType="Blog">
        select * from Blog where id = 1
    </select>-->
    <insert id="insertEmployee">
        insert into emp value (null, '姬如雪', 18, 2, '佛山');
    </insert>
</mapper>
    @Test
    public void testInsert() throws IOException {
        //获取对应的数据库配置信息(即要操作哪个数据库)
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//Resources.getResourceAsStream默认从类的根路径开始寻找文件
        //获取SqlSessionFactoryBuilder(通过该对象创建工厂)(一般一个数据库对应一个SqlSessionFactory)
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //获取SqlSessionFactory(通过该工厂创建SqlSession:Java程序和数据库之间的会话)
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        //获取SqlSession执行sql语句(即要操作哪张表)
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行sql语句
        int rows = sqlSession.insert("insertEmployee");
        //提交事务
        sqlSession.commit();
        System.out.println("rows:" + rows);
    }

上面测试代码的严谨写法

    @Test
    public void testSelectComplete() {
        SqlSession sqlSession = null;
        try {
            //获取SqlSessionFactoryBuild对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //获取SqlSessionFactory工厂
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
            //获取SqlSession会话
            sqlSession = sqlSessionFactory.openSession();
            int rows = sqlSession.insert("insertEmployee");
            sqlSession.commit();
            System.out.println("rows:" + rows);
        } catch (IOException e) {
            if (sqlSession != null) {
                sqlSession.rollback();
            }
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

2. 封装工具类SqlSessionUtil

由于每次都需要创建SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession对象,可以直接封装成工具类方便调用 

public class SqlSessionUtil {

    /*创建SqlSession工厂*/
    private static SqlSessionFactory sqlSessionFactory;

    /*随着类加载时配置好构造器(工厂)*/
    static {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /*一个线程对应一个会话*/
    private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();

    /*对外提供获取SqlSession方法*/
    public static SqlSession openSession() {
        SqlSession sqlSession = threadLocal.get();
        if (sqlSession == null) {
            sqlSession = sqlSessionFactory.openSession();
            threadLocal.set(sqlSession);
        }
        return sqlSession;
    }

    /*关闭SqlSession会话,将线程移除*/
    public static void close(SqlSession sqlSession) {
        if (sqlSession != null) {
            sqlSession.close();
            threadLocal.remove();
        }
    }

}
    @Test
    public void testSqlSessionUtil() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        int rows = sqlSession.insert("insertEmployee");
        sqlSession.commit();
        sqlSession.close();
        System.out.println("rows:" + rows);
    }

3. CRUD操作

3.1 增 

    #{} 占位符
1.如果传map对象:占位符里面的参数要和map集合中的键相一致才能获取map集合中的value值
2.如果传bean对象:占位符里面的参数要和bean对象的属性名保持一致才能获取bean对象的数据
<mapper namespace="EmployeeMapper">
    <insert id="insertEmployee">
        insert into emp values (null, #{name}, #{age}, #{deptId}, #{address})
    </insert>
</mapper>

方式一:通过传map对象

    @Test
    public void tesInsertEmployee() {
        SqlSession sqlSession = SqlSessionUtil.openSession();

        Map<String, Object> map = new HashMap<>();
        map.put("name", "肚肚龙");
        map.put("age", 3);
        map.put("deptId", 1);
        map.put("address", "广东");

        //执行sql语句  底层执行sql语句时会根据map集合的键占位符相匹配,若一致就将值赋给占位符#{}
        sqlSession.insert("insertEmployee", map);

        sqlSession.commit();
        sqlSession.close();
    }

方式二:通过传bean对象

public class Employee {
    private Integer id;
    private String name;
    private Integer age;
    private Integer deptId;
    private String address;
    @Test
    public void tesInsertEmployee() {
        SqlSession sqlSession = SqlSessionUtil.openSession();

        //执行sql语句  底层执行sql语句时会根据map集合的键占位符相匹配,若一致就将值赋给占位符#{}
        sqlSession.insert("insertEmployee", map);

        Employee e = new Employee(null, "肥奶龙", 2, 6, "江门");
        sqlSession.insert("insertEmployee", e);

        sqlSession.commit();
        sqlSession.close();
    }

3.2 删

<mapper namespace="EmployeeMapper">
    <delete id="deleteEmployee">
        delete from emp where id = #{id}
    </delete>
</mapper>
    @Test
    public void testDeleteEmployee() {
        //获取sql会话
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //执行sql语句,由于删除只需要一个参数,故随便传即可,他会自动识别
        int rows = sqlSession.delete("deleteEmployee", 10028);
        sqlSession.commit();
        sqlSession.close();
        System.out.println("rows:" + rows);
    }

 3.3 改

<mapper namespace="EmployeeMapper">
    <update id="updateEmployee">
        update emp set name = #{name}, age= #{age}, dept_id = #{deptId}, address = #{address} where id = #{id}
    </update>
</mapper>
    @Test
    public void testUpdateEmployee() {
        //获取sql会话
        SqlSession sqlSession = SqlSessionUtil.openSession();
        Employee e = new Employee(10027, "胖胖龙", 1, 9, "长沙");
        //执行sql语句
        int rows = sqlSession.update("updateEmployee", e);
        sqlSession.commit();
        sqlSession.close();
        System.out.println("rows:" + rows);
    }

3.4 查

注意:因为查询的列大多要和bean对象的字段进行反射映射匹配赋值,故列要起别名保证和bean对象字段名一致
查询还有返回类型,要指定给查询标签,通过类型反射赋值

为防止id冲突,需要引用命名空间,所有语句执行正确的写法为namespace.id

查询单个结果

<mapper namespace="EmployeeMapper">
    <select id="selectById" resultType="com.itgyl.mybatis.pojo.Employee">
        select id, name, age, dept_id deptId, address from emp where id = #{id}
    </select>
</mapper>
    @Test
    public void testSelectEmployeeById() {
        //获取sql会话
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //执行sql语句 selectOne查询返回一个bean对象
        Object employee = sqlSession.selectOne("selectById", 1);
        sqlSession.close();
        System.out.println(employee);
    }

查询所有结果

<mapper namespace="EmployeeMapper">
    <select id="selectAll" resultType="com.itgyl.mybatis.pojo.Employee">
        select id, name, age, dept_id deptId, address from emp
    </select>
</mapper>
    @Test
    public void testSelectEmployeeAll() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        /*查询所有bean对象存入list集合中并返回 最严谨写法:namespace.id*/
        List<Object> employeeList = sqlSession.selectList("EmployeeMapper.selectAll");
        for (Object o : employeeList) {
            System.out.println(o);
        }
        sqlSession.close();
    }

4. 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>
    <!--
    environments标签:
    环境可以有多个即可以同时配置多个数据库
        数据库不唯一,可以配置多个数据库信息即可以创建多个SqlSessionFactory工厂
        default的值为:不指定创建哪个SqlSessionFactory时默认使用id为default值的数据库
    -->
    <environments default="development">
        <environment id="development">
            <!--
            在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
            transactionManage标签:事务管理器
            1.作用:指定mybatis用什么方式进行管理事务
            2.有两个type类型:
                1.JDBC:使用原生的jdbc管理容器
                    coon.setAutoCommit(false)
                    ...
                    coon.commit()
                2.MANAGED:mybatis不再管理事务,将事务管理器交给其他容器管理如javaEE容器进行管理(spring)
            -->
            <transactionManager type="JDBC"/>

            <!--
            dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
            datasource:数据源
                1.作用:为程序提供Connection对象(但凡为程序提供Connection对象的都称为数据源)
                2.常见的数据源组件(常见的数据库连接池):druid等
                3.有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
                    1.UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。
                    2.POOLED:使用mybatis自带的数据库连接池
                    3.JNDI:集成其他第三方连接池
            -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/study"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <!--Mappers标签:
    路径映射,要操作的表
        表不唯一,可以同时配置多个表进行操作即可以创建多少SqlSession
    -->
    <mappers>
        <mapper resource="mapper/EmployeeMapper.xml"/>
    </mappers>
</configuration>
<?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 resource="jdbc.properties"></properties>
<settings>
<!--将表中字段的下划线自动转换为驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
<typeAliases>
<!--
typeAlias:设置某个具体的类型的别名
属性:
type:需要设置别名的类型的全类名
alias:设置此类型的别名,若不设置此属性,该类型拥有默认的别名,即类名且不区分大小
写
若设置此属性,此时该类型的别名只能使用alias所设置的值
-->
<!--<typeAlias type="com.atguigu.mybatis.bean.User"></typeAlias>-->
<!--<typeAlias type="com.atguigu.mybatis.bean.User" alias="abc">
</typeAlias>-->
<!--以包为单位,设置改包下所有的类型都拥有默认的别名,即类名且不区分大小写-->
<package name="com.atguigu.mybatis.bean"/>
</typeAliases>
<!--
environments:设置多个连接数据库的环境
属性:
default:设置默认使用的环境的id
-->
<environments default="mysql_test">
<!--
environment:设置具体的连接数据库的环境信息
属性:
id:设置环境的唯一标识,可通过environments标签中的default设置某一个环境的id,
表示默认使用的环境
-->
<environment id="mysql_test">
<!--
transactionManager:设置事务管理方式
属性:
type:设置事务管理方式,type="JDBC|MANAGED"
type="JDBC":设置当前环境的事务管理都必须手动处理
type="MANAGED":设置事务被管理,例如spring中的AOP
-->
<transactionManager type="JDBC"/>
<!--
dataSource:设置数据源
属性:
type:设置数据源的类型,type="POOLED|UNPOOLED|JNDI"
type="POOLED":使用数据库连接池,即会将创建的连接进行缓存,下次使用可以从
缓存中直接获取,不需要重新创建
type="UNPOOLED":不使用数据库连接池,即每次使用连接都需要重新创建
type="JNDI":调用上下文中的数据源
-->
<dataSource type="POOLED">
<!--设置驱动类的全类名-->
<property name="driver" value="${jdbc.driver}"/>
<!--设置连接数据库的连接地址-->
<property name="url" value="${jdbc.url}"/>
<!--设置连接数据库的用户名-->
<property name="username" value="${jdbc.username}"/>
<!--设置连接数据库的密码-->
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<mapper resource="UserMapper.xml"/>
<!--
以包为单位,将包下所有的映射文件引入核心配置文件
注意:此方式必须保证mapper接口和mapper映射文件必须在相同的包下
-->
<package name="com.atguigu.mybatis.mapper"/>
</mappers>
</configuration>

5. 动态sql

/*
* 动态SQL:
*   1.if标签:根据if标签中test属性中表达式决定标签中的内容是否要添加到sql语句中
*   2.where标签:
*       当where标签中有内容时会自动生成where关键字,并将内容前多余的and或or去掉
*       当where标签中没有内容则不会生成where关键字
*       注意:where标签不能将内容后多余的and或者or去掉
*   3.trim标签:
*       若标签中有内容:
*       prefix、suffix:可在内容前或内容后添加指定内容
*       prefixOverride、suffixOverride:可将内容前或内容后多余的and或or去掉
*       若标签中没有内容:则标签无效
*   4.choose、when、otherwise标签:相当于if... else if... else...语句
*       when最少一个,otherwise最多一个
*   5.foreach标签:用于实现批量操作
*       collection:设置需要循环的数组或集合
*       item:数组或集合中的数据
*       separator:如何分割sql语句条件
*       open:sql语句的条件以什么开头
*       close:sql语句的条件以什么结尾
*   eg:delete from emp where dept_id in ( ? , ? , ? )
*       此时separator值为, open值为(  close值为)  item值用于填充里面的占位符
*   6.sql标签:
*       可将要查看的字段写入sql标签中,后面查询语句直接引入该标签即可
*       eg:<sql id="empColumns">name, age, address</sql>
*           select <include refid="empColumns"></include> from emp
*           该查询语句实际为select name, age, address from emp
* */
<?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.itgyl.mybatis.mapper.DynamicSqlMapper">
    <!--int insertEmpByList(@Param("emps") List<Emp> list);-->
    <insert id="insertEmpByList">
        insert into emp values
                            <foreach collection="emps" item="emp" separator=",">
                                (null, #{emp.name}, #{emp.age}, #{emp.deptId}, #{emp.address})
                            </foreach>
    </insert>

    <!--int deleteEmpById(@Param("ids") Integer ids[]);-->
    <delete id="deleteEmpById">
        delete from emp where
        <foreach collection="ids" item="id" separator="or">
            dept_id = #{id}
        </foreach>
    </delete>

    <delete id="deleteEmpById1">
        delete from emp where dept_id in
               <foreach collection="ids" item="id" separator="," open="(" close=")">
                   #{id}
               </foreach>
    </delete>

    <!--List<Emp> getEmpByCondition(Emp emp);-->
    <!--sql片段,即查看数据的哪些字段可写入sql标签中,后面引用该sql标签即可-->
    <sql id="empColumns">name, age, address</sql>
    <select id="getEmpByCondition" resultType="Emp">
        select <include refid="empColumns"></include> from emp
        <!--select * from emp-->
        <where>
            <choose>
                <when test="name != null and name != ''">
                    name = #{name}
                </when>
                <when test="age != null and age != ''">
                    age = #{age}
                </when>
                <otherwise>
                    id = #{id}
                </otherwise>
            </choose>
        </where>
    </select>

    <select id="getEmpByCondition3" resultType="Emp">
        select * from emp
        <trim prefix="where" suffixOverrides="and|or">
            <if test="name != null and name != ''">
                name = #{name} or
            </if>
            <if test="age != null and age != ''">
                age = #{age}
            </if>
        </trim>
    </select>

    <select id="getEmpByCondition2" resultType="Emp">
        select * from emp
        <where>
            <if test="name != null and name != ''">
                name = #{name}
            </if>
            <if test="age != null and age != ''">
                and age = #{age}
            </if>
        </where>
    </select>

    <select id="getEmpByCondition1" resultType="Emp">
        select * from emp where 1 = 1
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        <if test="age != null and age != ''">
            and age = #{age}
        </if>

    </select>
</mapper>
 @Test
    public void testInsertEmpByList() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class);
        ArrayList<Emp> emps = new ArrayList<>();
        emps.add(new Emp(null, "a1", 1, 1, "66"));
        emps.add(new Emp(null, "a2", 1, 1, "66"));
        emps.add(new Emp(null, "a3", 1, 1, "66"));
        int rows = mapper.insertEmpByList(emps);
        sqlSession.commit();
        System.out.println(rows);
    }

    @Test
    public void testDeleteEmpById() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class);
        int rows = mapper.deleteEmpById(new Integer[]{6, 7, 8});
        sqlSession.commit();
        System.out.println(rows);
    }

    @Test
    public void testGetEmpByCondition() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class);
        List<Emp> list = mapper.getEmpByCondition(new Emp(null, null, null, 1, "新疆"));
        System.out.println(list);
    }

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

食懵你啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值