当前位置: 首页 > news >正文

Mybatis -- 使用

官网

 

入门_MyBatis中文网

依赖

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>

        <!-- mysql 连接 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>

引入Logback

Logback -- 使用_naki_bb的博客-CSDN博客

简单使用

配置文件目录结构

 mybatis-config.xml  -- 数据库连接以及Mappers信息

<?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.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>

UserMapper.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="test">
    <select id="selectAll" resultType="com.lb.pojo.User">
    select * from tb_user;
  </select>
</mapper>

测试:

public class MybatisDemo {

    public static void main(String[] args) throws IOException {
        //加载mybatis配置文件
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //获取sqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        
        //通过UserMapper.xml中的namespace和id,调用对应的sql
        List<User> users = sqlSession.selectList("test.selectAll");

        System.out.println(users);
        //关闭sqlSession
        sqlSession.close();
    }
}

通过入门已经可以使用的mybatis了,但是当Mapper过多时,每个都要添加,以及根据namespace的调用,不是很方便,则使用Mapper代理方式简化配置,以及方法调用

Mapper代理方式

注意事项:

1.定义与SQL映射文件同名的Mapper接口,并且Mapper接口和SQL映射文件放置在同一目录下

Mapper接口的目录需要和Mapper.xml文件目录一致,并且Resouce下创建文件不能使用“.”分割需要使用文件分隔符,否则编译完成,文件没有在同一目录下

 2.SQL映射文件的namespace属性为Mapper接口的全限定名

 3.在Mapper接口中定义方法,方案名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致

 4.如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL文件的加载

全部配置如下:

public interface UserMapper {

    List<User> selectAll();

    User selectById(Integer id);
}

 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 default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--
        <mapper resource="com/lb/mapper/UserMapper.xml"/>
         -->
        <!-- 直接包扫描 -->
        <package name="com.lb.mapper"/>
    </mappers>
</configuration>

 UserMapper.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.lb.mapper.UserMapper">

    <select id="selectAll" resultType="com.lb.pojo.User">
    select * from tb_user;
  </select>

    <select id="selectById" parameterType="Integer" resultType="com.lb.pojo.User">
        select * from tb_user where id = #{id};
    </select>
</mapper>

测试:

public class MybatisDemo {

    public static void main(String[] args) throws IOException {
        //加载mybatis配置文件
        String resource = "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);
        List<User> users = mapper.selectAll();

        User user = mapper.selectById(1);

        System.out.println(users);
        System.out.println(user);
        //关闭sqlSession
        sqlSession.close();
    }
}

字段属性名映射

当数据库列名与对象属性名称不一致时,建立映射关系

@Data
public class Brand {
    private Integer brandId;
    private String brandName;
    private String companyName;
    private String ordered;
    private String description;
    private String status;
}
<?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.lb.mapper.BrandMapper">

    <resultMap id="brandResultMap" type="com.lb.pojo.Brand">
        <!-- 设置列名和字段名的匹配 -->
        <!-- id映射-->
            <id column="id" property="brandId"/>
        <!-- 普通列映射 -->
            <result column="brand_name" property="brandName"/>
            <result column="company_name" property="companyName"/>
    </resultMap>

    <select id="selectAll" resultMap="brandResultMap">
        select * from tb_brand;
    </select>

</mapper>

返回类型 从resultType 替换 成 resultMap

请求参数

1.普通类型参数

    Brand selectByBrandId(int id);
    <!--
        根绝参数进行查询
        parameterType可以省略不写

        #{} -> 在生成sql时会替换成 ?
        ${} -> 在生成sql时会直接拼接到sql上,会有sql注入的风险
               如果在表名或者列名不确定时, 可以使用直接拼接sql
     -->
    <select id="selectByBrandId" parameterType="int" resultMap="brandResultMap">
        select * from tb_brand where id = #{id};
    </select>

 2.多个参数

    List<Brand> selectByParameter(
            @Param("status") int status, 
            @Param("brandName") String brandName, 
            @Param("companyName") String companyName);

 @Param 的 value 和 sql中的参数名必须一致

    <select id="selectByParameter" resultMap="brandResultMap">
        select * from tb_brand where
            status = #{status}
        and brand_name like #{brandName}
        and company_name like #{companyName}
    </select>

3.对象参数

List<Brand> selectByBrand(Brand brand);

 对象的属性名必须和sql中的参数名一致

    <select id="selectByBrand" resultMap="brandResultMap">
        select * from tb_brand where
            status = #{status}
        and brand_name like #{brandName}
        and company_name like #{companyName}
    </select>

4.Map参数

        Map map = new HashMap();
        map.put("status",status);
        map.put("brandName",brandName);
        map.put("companyName",companyName);

List<Brand> selectByMap(Map map);
    <select id="selectByMap" resultMap="brandResultMap">
        select * from tb_brand where
            status = #{status}
        and brand_name like #{brandName}
        and company_name like #{companyName}
    </select>

动态参数

IF 判断

    <select id="selectByBrand" resultMap="brandResultMap">
        select * from tb_brand
        where
        <if test="status != null">
            status = #{status}
        </if>
        <if test="brandName != null and brandName != ''">
            and brand_name like #{brandName}
        </if>
        <if test="companyName != null and companyName != ''">
            and company_name like #{companyName}
        </if>
    </select>

上面的sql,可以根据参数值是否存在动态的拼接sql,当除了status没值外,都可以正常运行。

当status没值时,报错,生成的sql如下

 因为where后的第一个参数不能带有and,所以需要使用<where> 标签来优化,它可以动态检查,看是否需要添加 and 关键字,需要给每一个参数添加 and 关键字

    <select id="selectByBrand" resultMap="brandResultMap">
        select * from tb_brand
        <where>
            <if test="status != null">
                and status = #{status}
            </if>
            <if test="brandName != null and brandName != ''">
                and brand_name like #{brandName}
            </if>
            <if test="companyName != null and companyName != ''">
                and company_name like #{companyName}
            </if>
        </where>
    </select>

Choose判断 

单一条件成立类似于Java 中的 switch

    <select id="selectByBrandSingle" resultMap="brandResultMap">
        select * from tb_brand
        <where>
            <choose> <!-- when条件只会有一个执行 -->
                <when test="status != null">
                    status = #{status}
                </when>
                <when test="brandName != null and brandName != ''">
                    brand_name like #{brandName}
                </when>
                <when test="companyName != null and companyName != ''">
                    company_name like #{companyName}
                </when>
                <!-- 都不成立时
               <otherwise></otherwise>
                -->
           </choose>
       </where>
   </select>

当参数都有值时,也会按照顺序判断,走第一个满足的条件。

特殊字符

  在xml中 < 是特殊字符
        解决方法:
        1.转义字符 &lt;
        2.   <![CDATA[内容]]>

插入insert

void addBrand(Brand brand);
    <insert id="addBrand" useGeneratedKeys="true" keyProperty="brandId">
        insert into tb_brand (brand_name, company_name, ordered, description, status) values
        (#{brandName},#{companyName},#{ordered},#{description},#{status});
    </insert>

注意

要添加 useGeneratedKeys="true" keyProperty="brandId" 设置ID回填,并且设置id的属性名.

在获取sqlSession时,sqlSessionFactory.openSession默认是手动提交事务,所以insert后需要手动提交,所以

SqlSession sqlSession = sqlSessionFactory.openSession(true);

使用以上获取sqlSession设置自动提交为true。则不需要手动提交事务。

更新update

    /**
     * @return 影响的行数
     */
    int updateBrand(Brand brand);
    <update id="updateBrand">
        update tb_brand
        <set>
            <if test="brandName != null and brandName != ''">
                brand_name = #{brandName},
            </if>
            <if test="companyName != null and companyName != ''">
                company_name = #{companyName},
            </if>
            <if test="ordered != null and ordered != ''">
                ordered = #{ordered},
            </if>
            <if test="description != null and description != ''">
                description = #{description},
            </if>
            <if test="status != null">
                status = #{status},
            </if>
            <if test="brandId != null">
                id = #{brandId},
            </if>
        </set>
        where id = #{brandId}
    </update>

 update可能参数为空,所以使用if标签动态添加,多余的“," set标签会处理。

为什么我的例子中set标签中会添加一个set id的 if标签,是为了防止当除了id以外其他的所有属性都不存在时,生成update tb_brand where id = ?这个sql,会到报错。所以设置一个恒等的标签,即使所有属性都为空,也不会报错。

删除delete

单个删除

// 返回值为删除的个数    
int deleteByBrandId(int id);
    <delete id="deleteByBrandId">
        delete from tb_brand where id = #{id} ;
    </delete>

多个删除

使用循环foreach,如果不使用@Param进行变量命名的化,sql直接写ids是不识别的,mybatis默认的变量名为array,所以如果不适用@Param则使用array来接受数组参数

//返回值是删除的个数
    int deleteByIds(@Param("ids") int[] ids);
    <delete id="deleteByIds">
        delete from tb_brand
        where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

参数封装

单个参数

1.POJO 类型: 直接使用,属性名 和参数占位符名称一致

2.Map集合:直接使用,键名 和 参数占位符名称一致

3.Collection: 封装成Map集合,可以使用@Param 注解,替换Map集合默认的arg键名

        map.put("arg0",collection集合);

        map.put("collection",collection集合)

4.List: 封装成Map集合,可以使用@Param 注解,替换Map集合默认的arg键名

        map.put("arg0",list集合);

        map.put("collection",list集合)

        map.put("list",list集合)

5.Array:封装成Map集合,可以使用@Param 注解,替换Map集合默认的arg键名

        map.put("arg0",数组);

        map.put("array",数组)

6.其他类型,直接使用

多个参数

封装成Map集合,可以使用@Param 注解,替换Map集合默认的arg键名

        map.put("arg0",参数1);

        map.put("param1",参数1);

        map.put("arg1",参数2);

        map.put("param2",参数2);

--------------------------------------@Param("username")

        map.put("username",参数1);

        map.put("param1",参数1);

        map.put("arg1",参数2);

        map.put("param2",参数2);

一对一查询

@Data
public class Employee {
   private Integer id;
   private String name;
   private String gender;
   private Dept dept;
}

@Data
public class Dept {
    private Integer id;
    private String name;
}

public interface EmployeeMapper {

    List<Employee> selectAll();
}
<?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.lb.mapper.EmployeeMapper">

    <resultMap id="employeeResultMap" type="com.lb.pojo.Employee">
        <!-- 如果包含association标签,即使其他属性和列名一致,也需要声明,否则映射不到 -->
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="gender" column="gender"></result>
        <!--
            association 这个标签对应employee中的dept成员变量属性
         -->
        <association property="dept" javaType="com.lb.pojo.Dept">
            <id property="id" column="dept_id"></id>
            <result property="name" column="dept_name"></result>
        </association>
    </resultMap>

    <select id="selectAll" resultMap="employeeResultMap">
        select e.*, d.id dept_id, d.name dept_name  from tb_emp e, tb_dept d where e.dept_id = d.id
    </select>
    
</mapper>

注意 

如果resultMap包含association标签,即使其他属性和列名一致,也需要声明,否则映射不到

一对多查询

@Data
public class Dept {
    private Integer id;
    private String name;
    List<Emp> employees;
}

@Data
public class Emp {
    private Integer id;
    private String name;
    private String gender;
}

public interface DeptMapper {
    List<Dept> selectAll();
}
<?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.lb.mapper.DeptMapper">

    <resultMap id="deptResultMap" type="com.lb.pojo.Dept">
        <id property="id" column="dept_id"/>
        <result property="name" column="dept_name"/>

        <collection property="employees" ofType="com.lb.pojo.Emp">
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="gender" column="gender"/>
        </collection>
    </resultMap>

    <select id="selectAll" resultMap="deptResultMap">
        select d.id dept_id, d.name dept_name, e.*  from tb_emp e, tb_dept d where e.dept_id = d.id
    </select>

</mapper>

 注意collection 使用的是ofType属性。

注解方式执行SQL

注解的方式只能执行一些简单的sql,如果sql比较复杂还是推荐使用xml的方式进行书写,如果使用注解会产生sql复杂,不易阅读,不易书写等诸多问题

    @Select("select * from tb_user where username = #{name}")
    User selectByName(String name);

    @Insert("insert into tb_user values(null,#{username},#{password},#{gender},#{addr})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(User user);

    @Update("update tb_user set username = #{username} where id = #{id}")
    int updateUserName(@Param("username") String username, @Param("id") int id);

    @Delete("delete from tb_user where id = #{id}")
    int delete(int id);

Idea 辅助工具

1.连接数据库

2.安装MybatisX 插件 -- 方便开发

 3.取消mapper.xml中的黄色以及绿色背景

去掉IDEA生成的mapper.xml中黄色和绿色的背景_一只小程序员啊的博客-CSDN博客_idea xml去掉绿色背景

整合Springboot

SpringBoot 整合 Mybatis_naki_bb的博客-CSDN博客

相关文章:

  • C语言双链表,循环链表,静态链表讲解(王道版)
  • 比较zab、paxos和raft的算法的异同
  • Python Argparse 库讲解特别好的
  • C++~从编译链接的过程看为什么C++支持重载?externC有什么用?
  • App移动端测试【10】Monkey自定义脚本案例
  • springboot 整合dubbo3开发rest应用
  • 【机器学习】集成学习:使用scikitLearn中的BaggingClassifier实现bagging和pasting策略
  • 算法与数据结构 --- 串,数组和广义表 --- 串
  • 【Python Web】Flask框架(四)Bootstrap的使用及案例
  • MySQL------数据表的创建和简单、条件,模糊查询
  • 【arduino】I/O端口操作
  • 微服务项目:尚融宝(44)(核心业务流程:借款申请(1))
  • 11、Java——吃货联盟订餐系统(对象+数组)
  • Java高性能实体类转换工具MapStruct
  • C++引用的概念
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 【css3】浏览器内核及其兼容性
  • 2017前端实习生面试总结
  • 2019年如何成为全栈工程师?
  • Centos6.8 使用rpm安装mysql5.7
  • Druid 在有赞的实践
  • JDK 6和JDK 7中的substring()方法
  • js递归,无限分级树形折叠菜单
  • ng6--错误信息小结(持续更新)
  • PermissionScope Swift4 兼容问题
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Promise面试题,控制异步流程
  • SegmentFault 2015 Top Rank
  • 不上全站https的网站你们就等着被恶心死吧
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 什么是Javascript函数节流?
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • #13 yum、编译安装与sed命令的使用
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • ${ }的特别功能
  • (+4)2.2UML建模图
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (数据结构)顺序表的定义
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (转)拼包函数及网络封包的异常处理(含代码)
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .axf 转化 .bin文件 的方法
  • .Net Web窗口页属性
  • .Net 代码性能 - (1)
  • .NET 的程序集加载上下文
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET成年了,然后呢?
  • .NET多线程执行函数
  • .NET企业级应用架构设计系列之开场白
  • .NET企业级应用架构设计系列之应用服务器
  • @Autowired 与@Resource的区别
  • [ vulhub漏洞复现篇 ] ECShop 2.x / 3.x SQL注入/远程执行代码漏洞 xianzhi-2017-02-82239600