3.mybatis第一个案例-查询

小试牛刀

上面的环境打好了以后,接下来就是对数据库的crud操作了。实际开发当中,查询是最常用的。所以我们来一个查询一张表的所有数据。

首先要在我们的mapper接口上创建一个查询的方法,由于我们是查询所有数据,那么肯定返回的是一个集合,那么我们就用List来接收,方法名称随便起,就叫selectAll()吧。然后在mapper对应的xml文件中,编写对应的sql语句。详细代码如下

public interface StudentMapper {

    /**
     * 查询所有
     * @return
     */
    List<Student> 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">
<!--这里的namespace取值就是接口全限定类目-->
<mapper namespace="com.bky.mapper.StudentMapper">
<!--    id属性值要和接口方法名一样(必须),resulType是查询后映射的实体类-->
    <select id="selectAll" resultType="com.bky.entity.Student">
        select *
        from student
    </select>
</mapper>

上面将主要的实现写完了,但是如何调用这个方法呢?那么我们要创建一个测试类,并且通过mybatis提供的api来实现这个接口(StudentMapper)。从而调用selectAll()方法。好的,直接上代码:

public class Test1 {
    public static void main(String[] args) throws IOException {
        //将配置文件变成输入流
        InputStream input = Resources.getResourceAsStream("mybatis-config.xml");
        //创建SqlSessionFactoryBuilder对象,用来解析输入流
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //解析输入流后生成SqlSessionFactory
        SqlSessionFactory factory = builder.build(input);
        //SqlSessionFactory生成SqlSession,本质上就是用SqlSession来跟数据库打交道
        SqlSession sqlSession = factory.openSession();
        //利用SqlSession提供的api来获取我们接口的实现类,这里用到了jdk的动态代理
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        //调用对应的接口方法
        List<Student> students = studentMapper.selectAll();
        for (Student student : students) {
            System.out.println("student = " + student);
        }
    }
}

控制台输出结果以及相关日志:

哈哈,只有一条数据。好的,完成了查询所有的演示。

很多同学看到这,会认为最终封装到的实体类只能是Student,其实不然。只要你的实体类字段能跟数据库对应上,都是能将结果集封装到你自己定义的实体类中的。只要在sql映射文件中做一个小小的修改就行。

好,接下来我们定义一个StudentDTO类,结构跟Student一样:

@Data
public class StudentDTO {
    /**
     *
     */
    private Long id;

    /**
     * 姓名
     */
    private String username;

    /**
     * 性别
     */
    private String gender;
}

我们将查询所有的方法返回值的list泛型变为他:

/**
     * 查询所有
     * @return
     */
    List<StudentDTO> selectAll();

修改对应的sql的返回值resultType

<select id="selectAll" resultType="com.bky.dto.StudentDTO">
        select *
        from student
</select>

不测试了,大家可以试一下。

接下来我们带条件查询,比如根据id查询,但是这个id是在实体类中,那么接口方法是这样

/**
     * 根据条件查询
     * @param student 条件值在对象中
     * @return
     */
    Student queryById(Student student);

上面我的注释写的是根据条件,是因为参数是一个实体类,而实体类中参数很多,所以你的查询条件就很灵活,可以根据id,username..... 而我这里只演示根据参数中的id查询,这里就用到mybatis提供的

来取值

<select id="queryById" resultType="com.bky.entity.Student" parameterType="com.bky.entity.Student">
        select * from student where id = #{id}
    </select>

mybatis别名配置

上面我们完成了一个简单的查询,接下来我们要给我们的实体类配置一个别名。请看我们的sql映射文件,resultType的属性值是一个全限定类名。我觉得麻烦。mybatis也很聪明,知道我们程序员很懒。于是提供了别名设置。

打开我们的mybatis的配置文件,只要增加如下配置,我们就可以使用别名了。

 

<configuration>
    <typeAliases>
<!--        给我们的实体类设置别名,可以写多个包路径-->
        <package name="com.bky.entity"/>
        <package name="com.bky.dto"/>
    </typeAliases>

当我们配置了别名以后,我们sql语句的返回类型就可以不用写包名了,直接写实体类的名称,并且大小写任意 

<select id="selectAll" resultType="studentDtO">
        select *
        from student
    </select>

<!--实际开发不要这么顽皮啊,写类的简单名称就行(StudentDTO),别像我这样搞事情。。。-->

好了,也很简单,我就不测试了。

上面这些简单的demo大家自己玩玩。有个小点要注意,如果你的sql语句查询会返回多个记录,而你的接口返回值是单个实体对象,那么这样会报错。

 

resultMap标签的使用

接下来有个令人难缠的问题,比如我现在数据库有个字段跟实体类不一样,比如这样:

对应实体类:

@Data
public class Student implements Serializable {
    /**
     * 
     */
    private Long id;

    /**
     * 姓名
     */
    private String username;

    /**
     * 性别
     */
    private String gender;

    /**
     * 女朋友,多个女朋友逗号隔开
     */
    private String girlFriends;

    private static final long serialVersionUID = 1L;
}

很显然,女朋友这个字段跟表字段对应不上。肯定封装不进来,不信我们测试一下,还是拿查询所有来测试

这样,他们的女朋友无缘无故消失了,究其原因,还是字段没对应上,怎么解决这个问题呢?

方法一,sql查询语句对应的字段起别名

我们现在就只是女朋友这个字段对应不上,那么在查询的时候,将女朋友这个字段单独捞出来起个别名就行,这个别名跟实体类女朋友字段一样就行:

<select id="selectAll" resultType="Student">
        select id,username,gender,girl_friends girlFriends
        from student
    </select>

是不是很简单,对,就这么简单。可是这样一来就有个小问题,如果我现在一个实体类有很多字段跟表字段对应不上,难道都起别名了吗?那不违背了程序员上班摸鱼的原则吗???于是,我们引出了resultMap标签

方法二,resultMap标签使用

换一个实体类吧,这个实体类咱们就多弄几个字段跟表字段对应不上。

@Data
public class Order {
    /**
     * 订单id,主键
     */
    private Long orderId;
    /**
     * 订单项
     */
    private String orderItem;
    /**
     * 下单时间
     */
    private Date createTime;
}

对应的表:

对应的mapper接口

public interface OrderMapper {

    List<Order> selectAll();
}

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.bky.mapper.OrderMapper">

    <select id="selectAll" resultType="com.bky.entity.Order">
        select * from my_order
    </select>
</mapper>

上面这个sql语句是不能进行结果集映射的,来个测试:

接下来,我只要略微出手,就可以查询到数据了,来,跟我练:

<?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取值就是接口全限定类目-->
<mapper namespace="com.bky.mapper.OrderMapper">

<!--    配置resultMap
id,在当前的xml文件里面必须唯一,因为resultMap可以配置多个,type就是你要映射的实体类
由于我们配置了别名,所以可以简写。
-->
    <resultMap id="orderMap" type="Order">
        <result property="orderId" column="order_id"/>
        <result property="orderItem" column="order_item"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

<!--    resultType换成resultMap-->
    <select id="selectAll" resultMap="orderMap">
        select * from my_order
    </select>
</mapper>

搞定!!!!

mybatis一对一查询

一对一查询也是一个常规操作,我现在有个爸爸表和一个妈妈表,对应实体如下

@Data
public class Father implements Serializable {
    /**
     * 
     */
    private Long id;

    /**
     * 
     */
    private String username;

    /**
     * 
     */
    private Integer age;
    
    private static final long serialVersionUID = 1L;
}
@Data
public class Mother implements Serializable {
    /**
     * 
     */
    private Long id;

    /**
     * 
     */
    private String motherName;

    /**
     * 关联的爸爸id
     */
    private Long fatherId;

    private static final long serialVersionUID = 1L;
}

一对一查询方式有很多,随便介绍几种吧,第一种就是我们新建一个dto类,然后将爸爸的字段和妈妈的字段全部塞到dto中去(当然你直接在father类添加mother字段也是可以的,懂得都懂)。

@Data
public class FatherDTO {
    /**
     * 爸爸id
     */
    private Long id;

    /**
     * 爸爸名字
     */
    private String username;

    /**
     * 爸爸年龄
     */
    private Integer age;

    /**
     * 妈妈id
     */
    private Long motherId;

    /**
     * 妈妈名字
     */
    private String motherName;

    /**
     * 关联的爸爸id
     */
    private Long fatherId;
}

对应的mapper方法:

public interface FatherMapper  {


    FatherDTO selectFatherAndMotherByFid(Long id);
}
<select id="selectFatherAndMotherByFid" resultType="FatherDTO">
        <!--这里的妈妈返回的字段要起别名,目的是为了跟FatherDTO对应上-->
        select f.*
             ,m.id motherId
             ,m.mother_name motherName
             ,m.father_id fatherId from father f
        left join mother m
        on f.id = m.father_id
        where f.id = #{id}
    </select>

好,这种方式大家要记住。

还有中方式就是将妈妈类嵌套在爸爸类中,这种方式也很多件,再来建立一个dto:

@Data
public class FatherInDTO {
    /**
     * 爸爸id
     */
    private Long id;

    /**
     * 爸爸名字
     */
    private String username;

    /**
     * 爸爸年龄
     */
    private Integer age;

    /**
     * 妈妈实体类
     */
    private Mother mother;
}

这时候呢,sql语句的写法会发生一些变化,不能直接去join查询了。我们来看看如何操作。

首先在father的xml文件中建立一个resultMap标签,这个标签有点特殊,要关联妈妈的相关信息和sql

<resultMap id="FinMMap" type="FatherInDTO">
        <id property="id" column="id" jdbcType="BIGINT"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
        <result property="age" column="age" jdbcType="INTEGER"/>
<!--    association就是这个结果集映射的一个嵌套
    property表示FatherInDTO中哪个嵌套对象,
    javaType 表示这个对象是什么类型
    select 表示查询妈妈的方法调用的是哪个
    colum 表示跟FatherInDTO中哪个字段关联,很显然,是FatherInDTO的id字段
    -->
        <association property="mother" javaType="com.bky.entity.Mother" select="com.bky.mapper.MotherMapper.selectByFatherId" column="id"></association>
    </resultMap>

对应妈妈的mapper接口和xml文件

public interface MotherMapper {

    Mother selectByFatherId(Long fId);
}
<?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.bky.mapper.MotherMapper">

    <resultMap id="BaseResultMap" type="com.bky.entity.Mother">
            <id property="id" column="id" jdbcType="BIGINT"/>
            <result property="motherName" column="mother_name" jdbcType="VARCHAR"/>
            <result property="fatherId" column="father_id" jdbcType="BIGINT"/>
    </resultMap>

    <sql id="Base_Column_List">
        id,mother_name,father_id
    </sql>
    <select id="selectByFatherId" resultMap="BaseResultMap">
        select * from mother where father_id = #{fId}
    </select>


</mapper>

来测试下吧:

好的,一对一讲完了,上面这些写法满足了大部分需求,肯定还有其他的写法。大家可以自己查阅一下。这里就不介绍了

mybatis一对多查询

一对多查询也是实战中经常用到的,跟一对一差不多,一对多也是类似的写法,比如我现在有父亲类和孩子类,一个父亲会有多个孩子。

@Data
public class Father implements Serializable {
    /**
     * 
     */
    private Long id;

    /**
     * 
     */
    private String username;

    /**
     * 
     */
    private Integer age;

    /**
     * 所有的孩子
     */
    private List<Children> childrenList;

}
@Data
public class Children implements Serializable {
    /**
     * 
     */
    private Long id;

    /**
     * 
     */
    private String username;

    /**
     * 
     */
    private Integer age;

    /**
     * 爸爸id
     */
    private Long fatherId;

}

我们在爸爸mapper接口定义一个查询某一个爸爸和他的所有孩子,根据爸爸的id查询

/**
     * 查询爸爸和他的所有孩子
     * @param fid 爸爸id
     * @return
     */
    Father selectFatherAndChildByFid(Long fid);

同样,还是要在爸爸的xml文件建立一个resultMap标签,这个标签就有查询多个孩子的用法,其实跟一对一差不多

<resultMap id="FatherChildMap" type="Father">
        <id property="id" column="id" jdbcType="BIGINT"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
        <result property="age" column="age" jdbcType="INTEGER"/>
<!--        一对多查询,用这个标签,
property 多的一方在一的一方的属性名
ofType 多的类型
column 关联的一的一方的字段
select 调用多的一方的哪个查询方法
-->
        <collection property="childrenList" ofType="com.bky.entity.Children" column="id" select="com.bky.mapper.ChildrenMapper.selectByFatherId">

        </collection>
    </resultMap>

<select id="selectFatherAndChildByFid" resultMap="FatherChildMap">
        select * from father where id = #{fid}
    </select>

多的一方(孩子)xml中的方法

<resultMap id="BaseResultMap" type="com.bky.entity.Children">
            <id property="id" column="id" jdbcType="BIGINT"/>
            <result property="username" column="username" jdbcType="VARCHAR"/>
            <result property="age" column="age" jdbcType="INTEGER"/>
            <result property="fatherId" column="father_id" jdbcType="BIGINT"/>
    </resultMap>

<select id="selectByFatherId" resultMap="BaseResultMap">
        select * from child_ren where father_id = #{fid}
    </select>

这样就行了,我们进行简单测试

mybatis多对多查询

多对多也是实际开发常用的,我现在有三张表,老师表班级表老师班级对应表

对应实体类

@Data
public class Classes implements Serializable {
    /**
     * 
     */
    private Long id;

    /**
     * 班级编号
     */
    private String classesNo;

    private static final long serialVersionUID = 1L;
}
@Data
public class Teacher implements Serializable {
    /**
     * 
     */
    private Integer id;

    /**
     * 教师工作证编号
     */
    private String teacherNo;

    /**
     * 教师姓名
     */
    private String username;

    private static final long serialVersionUID = 1L;
}
@Data
public class ClassTeacher implements Serializable {
    /**
     * 
     */
    private Long id;

    /**
     * 教师id
     */
    private Long teacherId;

    /**
     * 班级id
     */
    private Long classId;

    private static final long serialVersionUID = 1L;
}

那么现在有个需求就是根据教师的id查询对应班级下的所有老师,暂不查询班级,只查询老师。其实这个问题的难点并不是mybatis,而是对应的sql语句比较难。这是我写的sql语句,大家看一下:

SELECT
	* 
FROM
	teacher 
WHERE
	id IN (
	SELECT
		t.id 
	FROM
		teacher t
		INNER JOIN class_teacher ct ON t.id = ct.teacher_id 
	WHERE
		ct.class_id IN ( SELECT class_id FROM class_teacher WHERE teacher_id = 1 ) 
	GROUP BY
		t.id 
	)

Navicat工具执行的结果:

 上面这个sql是当老师id为1的时候查询出的所有老师,我们再次看一下老师班级中间表,看看结果对不对

那么sql语句都出来了,整个mybatis查询也容易了,我们在老师mapper接口新建方法

public interface TeacherMapper {

    /**
     * 根据教师id查询所有的教师
     * 就是说,一个老师对应多个班级,那么多个班级又对应
     * 多个老师,那么返回所有的老师
     * @param tid
     * @return
     */
    List<Teacher> selectAllById(Long tid);
}

对应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.bky.mapper.TeacherMapper">

    <resultMap id="BaseResultMap" type="Teacher">
        <id property="id" column="id" jdbcType="INTEGER"/>
        <result property="teacherNo" column="teacher_no" jdbcType="VARCHAR"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
    </resultMap>
    <select id="selectAllById" resultMap="BaseResultMap" parameterType="java.lang.Long">
        SELECT *
        FROM teacher
        WHERE id in
              (SELECT t.id
               FROM teacher t
                        INNER JOIN class_teacher ct ON t.id = ct.teacher_id
               WHERE ct.class_id IN (SELECT class_id FROM class_teacher WHERE teacher_id = #{tid})

               GROUP BY t.id)
    </select>


</mapper>

好,接下来我们将难度升级一点,根据老师id查询所有的老师和所有的班级。这个其实有很多方式,那我们来弄一个最简单的方式,

首先查询所有的老师,这个上面那个案例已经完成了,我们贴一下sql语句

SELECT *
        FROM teacher
        WHERE id in
              (SELECT t.id
               FROM teacher t
                        INNER JOIN class_teacher ct ON t.id = ct.teacher_id
               WHERE ct.class_id IN (SELECT class_id FROM class_teacher WHERE teacher_id = 1)

               GROUP BY t.id)

我们再查询这个老师对应的所有班级

SELECT
	* 
FROM
	classes 
WHERE
	id IN ( SELECT class_id FROM class_teacher WHERE teacher_id = 1 )

有了这两个sql语句,我们就可以利用mybatis提供的查询来封装这个结果集,我们在老师类里面加入班级类集合

@Data
public class Teacher implements Serializable {
    /**
     * 
     */
    private Integer id;

    /**
     * 教师工作证编号
     */
    private String teacherNo;

    /**
     * 教师姓名
     */
    private String username;

    /**
     * 对应的班级
     */
    private List<Classes> classesList;

    private static final long serialVersionUID = 1L;
}

在teacher的mapper接口新增一个方法

/**
     * 根据教师id查询所有老师和对应的班级
     * @param tid 老师id
     * @return
     */
    List<Teacher> selectTAndCBytid(Long tid);

对应的xml

<select id="selectTAndCBytid" resultMap="BaseResultMap2" parameterType="java.lang.Long">
        SELECT *
        FROM teacher
        WHERE id in
              (SELECT t.id
               FROM teacher t
                        INNER JOIN class_teacher ct ON t.id = ct.teacher_id
               WHERE ct.class_id IN (SELECT class_id FROM class_teacher WHERE teacher_id = #{tid})

               GROUP BY t.id)
    </select>

<resultMap id="BaseResultMap2" type="Teacher">
        <id property="id" column="id" jdbcType="INTEGER"/>
        <result property="teacherNo" column="teacher_no" jdbcType="VARCHAR"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
        <collection property="classesList" ofType="com.bky.entity.Classes" column="id" select="com.bky.mapper.ClassesMapper.queryByTid">

        </collection>
    </resultMap>

那么还要在班级mapper接口添加方法

public interface ClassesMapper  {

    /**
     * 根据老师id查询所有班级
     * @param tid
     * @return
     */
    List<Classes> queryByTid(Long tid);

}

 对应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.bky.mapper.ClassesMapper">

    <resultMap id="BaseResultMap" type="com.bky.entity.Classes">
        <id property="id" column="id" jdbcType="BIGINT"/>
        <result property="classesNo" column="classes_no" jdbcType="VARCHAR"/>
    </resultMap>
    <select id="queryByTid" resultMap="BaseResultMap" parameterType="java.lang.Long">
        SELECT
            *
        FROM
            classes
        WHERE
            id IN ( SELECT class_id FROM class_teacher WHERE teacher_id = #{tid} )
    </select>
</mapper>

好了,这就搞定了。做个简单的测试

List<Teacher> teachers = this.teacherMapper.selectTAndCBytid(1l);
        for (Teacher teacher : teachers) {
            System.out.println("当前老师"+teacher);
            System.out.println("对应的班级↓↓↓↓↓↓↓↓");
            List<Classes> classesList = teacher.getClassesList();
            for (Classes classes : classesList) {
                System.out.println("classes = " + classes);
            }
        }

但是这个美中不足的是,在查询班级的时候会多次查询数据库。这个是mybatis机制问题。后续我们看看有没有办法一个sql语句将结果查询并且封装好。

 

mybatis批量查询

批量查询也是我们实际开发经常用的,比如现在通过id批量查询订单

先看下表数据吧

就两条,id为1,2

那么sql语句就是

SELECT * FROM my_order WHERE order_id IN (1,2)

实际开发我们肯定不是in后面的参数写死,而是动态生成的,怎么做呢?首先还是一样,在mapper接口创建方法,返回肯定是list结构,而方法的参数肯定也是id集合,因为是批量查询嘛。

public interface OrderMapper {

    List<Order> selectByIds(List<Long> ids);
}

对应xml

<select id="selectByIds" resultMap="orderMap">
        select * from my_order
        where order_id in
        <!--这里使用这个标签来动态生成()内容 开始(,分隔符用,最后结束用)
        还是很容易明白的
        -->
        <foreach collection="ids" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>


<resultMap id="orderMap" type="Order">
        <result property="orderId" column="order_id"/>
        <result property="orderItem" column="order_item"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

好,我们来测试看看

List<Order> orders = this.orderMapper.selectByIds(Arrays.asList(1l, 2l));
        for (Order order : orders) {
            System.out.println("order = " + order);
        }

运行代码,控制台发现报错了。。。。

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'ids' not found. Available parameters are [arg0, collection, list]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'ids' not found. Available parameters are [arg0, collection, list]


//整个堆栈省略

报错的内容好像是在告诉我们参数ids找不到?这是怎么回事呢?带着疑问,我们进行下一个知识点的学习。

 

@Param 使用

刚才留下了一个问题,就是为什么找不到我们传递的ids参数,原来是我们少加了一个注解,就是@Param 这个注解,加在什么地方呢?直接上代码

//加上这个注解,mybatis就能识别到你传递的参数了
List<Order> selectByIds(@Param("ids") List<Long> ids);

我们再次测试,发现控制台打印的sql语句也对了

很奇怪,为什么要加这个注解呢?这个以后有机会得看mybatis的源码了。现在我们得熟练使用mybatis。

其实这个注解应该在一上来就讲,但是总感觉不知道从哪里入口。正好批量查询必须使用这个注解。所以引用出来了。下面找几个代表性的用法来玩玩。

比如现在我要查询father表,根据姓名或者年龄查询,而姓名和年龄分别来自两个不同的对象。比如

/**
     * 根据姓名或者年龄查询
     * @param username 这个参数提供姓名
     * @param age 这个参数提供年龄
     * @return
     */
    List<Father> selectByNameOrAge(Father username,Father age);

对应的xml

<select id="selectByNameOrAge" resultMap="BaseResultMap">
        select *
        from father
        where username = #{username}
        or age = #{age}
    </select>

这是个错误的示范,因为mybatis被你搞晕了,我这是去哪个对象的username和age呢?所以这时候你得告诉mybatis,那么@Param注解的作用就来了。改造后的代码

/**
     * 根据姓名或者年龄查询
     * @param username 这个参数提供姓名
     * @param age 这个参数提供年龄
     * 注解中的参数名称随便起,但是在当前方法内不允许重复
     * @return
     */
    List<Father> selectByNameOrAge(@Param("p1") Father username,@Param("p2") Father age);
<select id="selectByNameOrAge" resultMap="BaseResultMap">
        select *
        from father
        where username = #{p1.username}
        or age = #{p2.age}
    </select>

就是这么简单,我们测试一下

Father username = new Father();
        username.setUsername("张飞");
        Father age = new Father();
        age.setAge(25);
        List<Father> fathers = this.fatherMapper.selectByNameOrAge(username, age);
        for (Father father : fathers) {
            System.out.println("father = " + father);
        }

建议在每个mapper方法中都使用这个注解

 

mybatis分页查询

关于分页查询呢,mybatis自身提供了一个组件,但是那个很少用,也麻烦。mybatis作为一个强大的持久层框架呢,提供了一个很牛逼的扩展点,插件机制。这个插件机制确实牛逼,他可以干很多事情。这个插件本质上就是拦截器,可以在sql执行之前进行拦截,也可以在sql执行之后进行拦截。如果开发者能够熟练使用插件。那么对你开发而言将事半功倍。好,我们先来使用这个分页插件。首先引入依赖

<dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>3.5.1</version>
    </dependency>

然后在mybatis的xml配置文件中配置插件和相关参数

<plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!--            配置哪种数据库的分页,因为很多数据库的分页写法不一样
                            所以得告诉插件我现在用的是什么数据库
                            可选的值有 mysql,mariadb,sqlite,oracle,hsqldb,postgresql
                            全部小写
            -->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>

在mapper接口中写个分页查询

/**
     * 分页查询,这个page本质就是list,但是里面有分页参数
     * @return
     */
    Page<Father> selectPage();

贴下page的源码

本质上就是list,但是他里面有分页的参数,比如第几页,当前页的个数。

对应xml查询语句,也很简单

<select id="selectPage" resultType="com.bky.entity.Father">
        select * from father
    </select>

然后在我们进行查询之前,调用这个插件的api。

/**
         * 第一个参数是第几页,这里我从第一页开始查询
         * 第二个参数就是每页查询几条
         */
        PageHelper.startPage(2,3);
        Page<Father> fathers = this.fatherMapper.selectPage();
        for (Father father : fathers) {
            System.out.println("father = " + father);
        }

 

posted @   诸葛匹夫  阅读(44)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示