MyBatis拓展

MyBatis 拓展

1.配置解析

setting(设置)
typeAliases(类型别名)
environments(环境配置)
mappers(映射器)

注意顺序,顺序不对也会报错

1.1 typeAliases

之前在mapper.xml文件中写结果类型或参数类型都会使用全限定类名,使用 别名后,在结果类型处可直接使用别名,采用别名的方式有3种:

  • 指定一个实体类给一个别名

    <typeAliases>
            <typeAlias type="com.zxjava.pojo.User" alias="User"/>
    </typeAliases>
    
  • 指定一个包,扫描包下的Java Bean

        <typeAliases>
            <package name="com.zxjava.pojo"/>
        </typeAliases>
    
  • 在实体类上使用注解

    @Alias("user")
    public class User {
       .....
    }
    

1.2 mappers

  • 使用相对于类路径的资源引用

        <mappers>
            <mapper resource="com/zxjava/dao/UserMapper.xml"/>
        </mappers>
    
  • 将包内的映射器接口全部注册为映射器

    (接口文件名和配置文件名需一致,并且在同一目录下)

        <mappers>
            <package name="com.zxjava.dao"/>
        </mappers>
    

2. ResultMap

ResultMap时解决数据库字段名和实体类属性名不一致的问题

    <resultMap id="userMap" type="user">
        <!--id是主键-->
        <id column="id" property="id"/>
        <result column="name" property="mingzi"/>
        <result column="password" property="mima"/>
    </resultMap>

3.日志工厂

首先在pom文件中导入log4j的包

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

在resources中新建log4j.properties

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/ws.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

在配置文件中加入settings

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

4. 分页

4.1 Limit分页

  • ​ 语法:select * from table limit startIndex,pageSize

    ​ 从startIndex开始查找pageSize个

  • ​ 语法:select * from table limit num

    ​ 从第0个开始查找num个 , 相当于把上一种startIndex为0 省略

测试:

首先在userMapper中新增一个方法

    //分页查找
    List<User> selectByLimit(Map<String,Integer> map);

在配置文件中新增一条语句

    <select id="selectByLimit" parameterType="java.util.Map" resultType="user">
        select * from user limit #{currentPage},#{pageSize}
    </select>

在测试类中测试

    @Test
    public void selectByLimit(){
        SqlSession session = MybatisUtil.getSession();

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

        Map<String,Integer> map = new HashMap<>();

        int currentPage = 2;//第几页

        int pageSize = 1;//每页几条

        map.put("currentPage",(currentPage-1)*pageSize);
        map.put("pageSize",pageSize);

        List<User> users = mapper.selectByLimit(map);

        for (User user : users) {
            System.out.println(user);
        }

        session.close();
    }

4.2 RowBounds分页

RowBounds分页不推荐使用

首先在userMapper中新增一个方法

    //RowBounds
    List<User> selectByRowBouns();

在配置文件中新增一条语句

    <select id="selectByRowBouns" resultType="user">
        select * from user
    </select>

在测试类中测试

    @Test
    public void selectByRowBouns(){
        SqlSession session = MybatisUtil.getSession();

        int currentPage = 2;//第几页

        int pageSize = 2;//每页几条

        RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);

        List<User> users = session.selectList("com.zxjava.dao.UserMapper.selectByRowBouns",null,rowBounds);

        for (User user : users) {
            System.out.println(user);
        }



        session.close();
    }

4.3 PageHelper分页插件

PageHelper是一款比较好用的分页插件,官网有详细的使用教程,下面超链接可访问官网。
PageHelper官网

5. 使用注解开发

5.1查询

首先编写接口的方法

package com.zxjava.dao;


import com.zxjava.pojo.User;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface UserMapper {

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

}

编写测试类

import com.zxjava.dao.UserMapper;
import com.zxjava.pojo.User;
import com.zxjava.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;


public class MybatisTest {

    @Test
    public void selectUsers(){

        SqlSession session = MybatisUtil.getSession();

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

        List<User> users = mapper.selectUsers();

        for (User user : users) {
            System.out.println(user);
        }

        session.close();
    }
}

5.2 根据ID查询

首先编写接口的方法

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

@param中的参数与数据库保持一致即可

编写测试类

    @Test
    public void selectUserById(){

        SqlSession session = MybatisUtil.getSession();

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

        User user = mapper.selectUserById(1);

        System.out.println(user);

        session.close();
    }

5.3增加

首先编写接口的方法

    @Insert("insert into user(id,name,password) values (#{id},#{name},#{password})")
    void insertUser(User user);

编写测试类

    @Test
    public void insertUser(){
        SqlSession session = MybatisUtil.getSession();

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

        User user = new User(4,"钢铁侠","hero");

        mapper.insertUser(user);

        session.commit();
        session.close();
    }

5.4 修改

首先编写接口的方法

    @Update("update user set name = #{name} , password = #{password} where id = #{id}")
    void updateUser(User user);

编写测试类

    @Test
    public void updateUser(){

        SqlSession session = MybatisUtil.getSession();

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

        User user = new User(4,"美国队长","coolman");

        mapper.updateUser(user);

        session.commit();
        session.close();

    }

5.5 删除

首先编写接口的方法

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

编写测试类

    @Test
    public void deleteUser(){
        SqlSession session = MybatisUtil.getSession();

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

        mapper.deleteUser(4);

        session.commit();
        session.close();
    }

6.多对一和一对多

创建老师表,添加数据

create table teacher(
    id int(10) not null,
    name varchar(30),
    primary key (id));
    
insert into teacher(id,name) values (1,"王老师");

创建学生表,添加数据

create table student(
    id int(10) not null, 
    name varchar(30) default null, 
    tid int(10) default null,
    primary key (id), 
    foreign key (tid) references teacher (id));
    
    
   
insert into student(id , name, tid) values (1,"小李",1);
insert into student(id , name, tid) values (2,"小陈",1);
insert into student(id , name, tid) values (3,"小花",1);

创建老师实体类

package com.zxjava.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Teacher {
    private int id;
    private String name;
}

创建学生实体类

package com.zxjava.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Student {
    private int id;
    private String name;
    private Teacher teacher;
}


(接口和配置文件省略)

6.1多对一(第一种)

多个学生对应(关联)一个老师

获取所有学生对应老师的信息

首先编写接口的方法

package com.zxjava.dao;

import com.zxjava.pojo.Student;

import java.util.List;

public interface StudentMapper {

    List<Student> getStudents();
}

编写配置文件

<?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.zxjava.dao.StudentMapper">



    <select id="getStudents" resultMap="StudentTeacher">
        select * from student
    </select>

    <resultMap id="StudentTeacher" type="Student">
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>

    <select id="getTeacher" resultType="teacher">
        select * from teacher where id = #{id}
    </select>

</mapper>

编写测试类

    @Test
    public void getStudents(){
        SqlSession session = MybatisUtil.getSession();

        StudentMapper mapper = session.getMapper(StudentMapper.class);

        List<Student> students = mapper.getStudents();

        for (Student student : students) {
            System.out.println(student);
        }


        session.close();
    }

6.2 多对一(第二种)

多对一的第二种方式是按结果集映射

首先在接口中编写一个方法


    //按结果集映射
    List<Student> getStudents2();

编写对应的Mapper文件

    <select id="getStudents2" resultMap="StudentTeacher2">
        select s.id sid,s.name sname,t.id tid,t.name tname from student s,teacher t where s.tid = t.id
    </select>

    <resultMap id="StudentTeacher2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="id" column="tid"/>
            <result property="name" column="tname"/>
        </association>
    </resultMap>

编写测试类

    @Test
    public void getStudents2(){
        SqlSession session = MybatisUtil.getSession();

        StudentMapper mapper = session.getMapper(StudentMapper.class);

        List<Student> students2 = mapper.getStudents2();

        for (Student student : students2) {
            System.out.println(student);
        }

        session.close();
    }

ps: 多对一和一对多选择第一种方式还是第二种方式根据自己的习惯,个人推荐第二种,按结果集映射

6.3 一对多

一个老师对应多个学生

编写老师实体类

package com.zxjava.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Teacher {

    private int id;

    private String name;

    private List<Student> students;
}

编写学生实体类

package com.zxjava.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Student {
    private int id;

    private String name;

    private  int tid;
}

编写一对多的接口

package com.zxjava.dao;

import com.zxjava.pojo.Teacher;

public interface TeacherMapper {

    Teacher getTeacher( int id);
}

接口对应的Mapper文件

<?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.zxjava.dao.TeacherMapper">


    <select id="getTeacher" resultMap="TeacherStudent">
        select t.id tid,t.name tname,s.id sid,s.name sname,s.tid stid from teacher t,student s where t.id = s.tid and t.id = #{id};
    </select>

    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="stid"/>
        </collection>
    </resultMap>

</mapper>

测试类测试

import com.zxjava.dao.TeacherMapper;
import com.zxjava.pojo.Teacher;
import com.zxjava.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class MyTest {

    @Test
    public void getTeacher(){
        SqlSession session = MybatisUtil.getSession();

        TeacherMapper mapper = session.getMapper(TeacherMapper.class);

        Teacher teacher = mapper.getTeacher(1);

        System.out.println(teacher);

        session.close();
    }
}

测试结果

在这里插入图片描述

展示目录结构方便开发:

在这里插入图片描述

最后做个总结的话就是:

  • 多对一或一对多按结果集映射比较推荐
  • 多对一用association 一对多用collection

7.动态SQL

动态SQL是Mybatis最强大的特性之一,通过if 、choose、when、otherwise、where、set、foreach等标签组合成非常灵活的SQL语句

首先创建表格

 create table blog(
            id varchar(50) not null primary key ,
            title varchar(100) not null ,
            author varchar(30) not null ,
            create_time datetime not null ,
            views int(30) not null 
        )

创建Blog实体类

package com.zxjava.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.Date;


@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Blog {
    private String id;

    private String title;

    private String author;

    private Date createTime;

    private int views;
}

编写Mybatis核心配置文件,下划线驼峰自动转换

<settings>
    <setting name="logImpl" value="LOG4J"/>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

写一个生成UUID的工具类

package com.zxjava.utils;

import java.util.UUID;

public class UUIDutils {
    public static String getId(){
        return UUID.randomUUID().toString().replace("-","");
    }
}

7.1 回顾

回顾一下之前的增加方法

在接口中编写一个增加方法

package com.zxjava.dao;

import com.zxjava.pojo.Blog;

public interface BlogMapper {

    void addBlog(Blog blog);
}

编写对应的配置文件

<?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.zxjava.dao.BlogMapper">


    <insert id="addBlog" parameterType="blog">
        insert into blog(id,title,author,create_time,views) values (#{id},#{title},#{author},#{createTime},#{views})
    </insert>

</mapper>

编写测试类

import com.zxjava.dao.BlogMapper;
import com.zxjava.pojo.Blog;
import com.zxjava.utils.MybatisUtil;
import com.zxjava.utils.UUIDutils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.Date;

public class MyTest {

    @Test
    public void addBlog(){
        SqlSession session = MybatisUtil.getSession();

        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Blog blog = new Blog();
        blog.setId(UUIDutils.getId());
        blog.setTitle("动态SQL");
        blog.setAuthor("小王");
        blog.setCreateTime(new Date());
        blog.setViews(2);

        mapper.addBlog(blog);

        session.commit();
        session.close();
    }
}

7.2 if

如果我们想根据作者名字和标题来查询博客,但如果标题为空,怎么办?

在接口中增加一个方法

List<Blog> selectBlog(Map<String,String> map);

在接口对应的Mapper文件中增加语句

    <select id="selectBlog" parameterType="java.util.Map" resultType="blog">
        select * from blog where
        <if test="author != null">
            author = #{author}
        </if>

        <if test="title != null">
            and title = #{title}
        </if>
    </select>

编写测试类

    @Test
    public void selectBlog(){
        SqlSession session = MybatisUtil.getSession();

        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Map<String,String> map = new HashMap<>();
        map.put("author","小王");

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

        for (Blog blog : blogs) {

            System.out.println(blog);

        }

        session.close();
    }

执行的语句

在这里插入图片描述

if语句并不难理解,但在使用if时,可以在映射文件中明显看到还是有很大的局限性,比如 如果author为空而title不为空时,会多出一个and符号,从而致使sql语法错误,而下面说的Where就是解决这个问题的。

7.3 where

如果标签返回的内容是以 and 或 or 开头的,where标签会把它们去掉。

修改上面的SQL语句

    <select id="selectBlog" parameterType="java.util.Map" resultType="blog">
        select * from blog
        <where>
            <if test="author != null">
                author = #{author}
            </if>

            <if test="title != null">
                and title = #{title}
            </if>
        </where>

    </select>

7.4 set

set标签用在update语句上,如果标签返回的内容是以,(逗号) 开头的,set标签会把它们去掉。

在接口中新增一个修改方法

void updateBlog(Map<String,String> map);

在映射文件中新增一个语句

    <update id="updateBlog" parameterType="java.util.Map">
        update blog
        <set>
            <if test="author != null">
                author = #{author}
            </if>

            <if test="title != null">
                ,title = #{title}
            </if>
            where id = #{id};
        </set>
    </update>

新增一个测试方法

    @Test
    public void updateBlog(){

        SqlSession session = MybatisUtil.getSession();

        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Map<String,String> map = new HashMap<>();

        map.put("author","老王啊");
        map.put("id","9b3708392cee4cddbad9aca6a31c425b");

        mapper.updateBlog(map);

        session.commit();
        session.close();

    }

注意: where标签和set标签去掉的是以 and or 或 ,***开头***而不是结尾的

7.5 choose

choose语句类似于Java中的switch语句,在我们只想选择一个查询条件时,可以用choose

在接口中新增一个方法

List<Blog> selectByChoose(Map<String,String> map);

在映射文件中新增一个语句

    <select id="selectByChoose" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <choose>
                <when test="title != null">
                    title = #{title}
                </when>
                <when test="author != null">
                    author = #{author}
                </when>
                <otherwise>
                    views  = #{views}
                </otherwise>
            </choose>
        </where>
    </select>

编写测试类

    @Test
    public void selectByChoose(){
        SqlSession session = MybatisUtil.getSession();

        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Map<String,String> map = new HashMap<>();

        map.put("author","小王");

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

        for (Blog blog : blogs) {
            System.out.println(blog);
        }

        session.close();
    }

7.6 sql片段

sql片段就是把一段sql代码抽离出来,然后再sql语句中再通过include引用这段sql代码即可,那我们以上面的choose标签为例,把映射文件的语句修改一下:

    <sql id="choose-title-author">
        <choose>
            <when test="title != null">
                title = #{title}
            </when>
            <when test="author != null">
                author = #{author}
            </when>
            <otherwise>
                views  = #{views}
            </otherwise>
        </choose>
    </sql>

    <select id="selectByChoose" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <include refid="choose-title-author"></include>
        </where>
    </select>

7.7 foreach

foreach标签中的属性:

  • collection:传递的集合
  • item:每次遍历生成的对象
  • open:开始遍历拼接的字符
  • close:结束遍历拼接的字符
  • separator:每次遍历之间的分隔符

在接口中新建一个方法

List<Blog> selectForeach(Map<String,List> map);

在映射文件中新增一个sql语句

    <select id="selectForeach" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <foreach collection="authors" item="author" open="(" close=")" separator="or">
                author = #{author}
            </foreach>
        </where>
    </select>

测试方法

    @Test
    public void selectForeach(){
        SqlSession session = MybatisUtil.getSession();

        BlogMapper mapper = session.getMapper(BlogMapper.class);

        List<String> authors = new ArrayList<>();

        authors.add("小王");
        authors.add("老王啊");

        Map<String,List> map = new HashMap<>();
        map.put("authors",authors);

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

        for (Blog blog : blogs) {

            System.out.println(blog);

        }

        session.close();
    }


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值