操作数据库更简单了。

1. 什么是Mybatis

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

以上为官方如是说

Mybatis简介

在我看下Mybatis就是一个方便我们对数据库进行操作的工具,仅此而已(浅理解。

这次用IDEA进行操作,也算是为后面学习做铺垫了。

1.1 Maven配置

创建Maven项目,在pom.xml中配置依赖

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

<!-- mysql数据库驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>

我这里用的是3.4.0版本的。

1.2 Mybatis_demo 数据库创建

我用的是mysql数据库,用的Navicat进行操作。

建库建表语句如下:

CREATE DATABASE Mybatis_demo

CREATE TABLE article(
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(32) DEFAULT NULL,
author VARCHAR(32) DEFAULT NULL
)AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO article VALUES (null,'白夜行','东野圭吾');
INSERT INTO article VALUES (null,'龙族','江南');

1.3 目录结构以及 MyBatis 配置文件创建

先创建如下的目录结构:

将java文件夹和resourse文件夹右键分别设置成Sources Root和Resources Root,也就是源代码目录和资源文件目录。

  1. 创建Article Pojo

    package com.x2y.pojo;   public class Article {
    private int id;
    private String title;
    private String author;

    public int getId() {
    return id;
    }

    public void setId(int id) {
    this.id = id;
    }

    public String getTitle() {
    return title;
    }

    public void setTitle(String title) {
    this.title = title;
    }

    public String getAuthor() {
    return author;
    }

    public void setAuthor(String author) {
    this.author = author;
    }

    @Override
    public String toString() {
    return id+"-"+ title+ "-"+ author;
    }
    }
  2. 创建Mapper文件 Article.xmlj

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.x2y.pojo">
<select id="listArticle" resultType="Article">
select * from article
</select>
</mapper>

这里只写了一个查询做测试。

  1. mybatis-config.xml文件

非常关键的配置文件,关于数据的链接信息以及Mybatis扫描路径的配置都在这。

XML 配置文件中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。

<?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>
<!-- 实体类路径-->
<typeAliases>
<package name="com.x2y.pojo"/>
</typeAliases>
<!-- 连接数据库信息-->
<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://localhost:3306/mybatis_demo?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- mapper扫描路径-->
<mappers>
<mapper resource="com/x2y/mapper/Article.xml"/>
</mappers>
</configuration>

1.4 创建测试类

测试类

package com.x2y.test;

import com.x2y.pojo.Article;
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;
import java.util.List;


public class TestMyBatis {
public static void main(String[] args)throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();

List<Article> as = session.selectList("listArticle");
for(Article a:as){
System.out.println(a.toString());
}
}
}

我们采用的是从 XML 中构建 SqlSessionFactory
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。

有了 SqlSessionFactory,我们就可以从中获得 SqlSession 的实例了。SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。

运行过后发现报错Could not find resource com/x2y/mapper/Article.xml

原来问题是在IDAE中直接把资源文件放在src文件夹下,如果不进行设置,是不能被找到的。
例如使用Mybatis,mapper文件都是放在包路径下,和实体一个层级,使用IDEA时就会报错。

解决方案
配置maven的pom文件配置,在pom文件中找到节点,添加下列代码:

<build>  
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>

*/.xml是通配符,匹配src/main/java目录下所有的xml文件,将其映射为资源文件,这样,IDEA就会加载该xml文件。

运行结果如下:
控制台打印
1-白夜行-东野圭吾
2-龙族-江南

2. Mybatis 的增删改查

从最简单CRUD开始,然后进一步的实现模糊查询,一对多,多对一,多对多的查询等等。

2.1 Mybatis CRUD

1.增
Mapper

<insert id="addArticle" parameterType="Article">
insert into article values (null,#{title},#{author})
</insert>

Test代码

package com.x2y.test;

import com.x2y.pojo.Article;
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;
import java.util.List;


public class TestMyBatis {
public static void main(String[] args)throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();

Article article = new Article();
article.setTitle("我的作品");
article.setAuthor("x2y");
session.insert("addArticle",article);

List<Article> as = session.selectList("listArticle");
for(Article a:as){
System.out.println(a.toString());
}
}
}

输出结果
1-白夜行-东野圭吾
2-龙族-江南
3-我的作品-x2y


  1. Mapper
    <delete id="deleteArticle" parameterType="int">
    delete from article where id=#{id}
    </delete>

测试

Article article = new Article();
article.setId(3);
session.delete("deleteArticle",article.getId());

List<Article> as = session.selectList("listArticle");
for(Article a:as){
System.out.println(a.toString());
}

将刚刚增加的删除掉了。


  1. Mapper
    <update id="updateArticle" parameterType="Article">
    update article set title=#{title},author=#{author}where id=#{id}
    </update>

测试

Article article = new Article();
article.setId(2);
article.setTitle("龙族-火之晨曦");
article.setAuthor("江南");

session.update("updateArticle",article);

List<Article> as = session.selectList("listArticle");
for(Article a:as){
System.out.println(a.toString());
}

输出
1-白夜行-东野圭吾
2-龙族-火之晨曦-江南


  1. 查一开始就示范了,每一步也有用。
    这里给出CRUD完整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.x2y.pojo">
    <select id="listArticle" resultType="Article">
    select * from article
    </select>

    <insert id="addArticle" parameterType="Article">
    insert into article values (null,#{title},#{author})
    </insert>

    <delete id="deleteArticle" parameterType="int">
    delete from article where id=#{id}
    </delete>

    <update id="updateArticle" parameterType="Article">
    update article set title=#{title},author=#{author}where id=#{id}
    </update>
    </mapper>

2.2 模糊查询和多条件查询

模糊查询的一些简单总结

  1. 模糊查询
    Mapper
    <select id="listArticleFuzzy" parameterType="string" resultType="Article">
    select * from article where title like concat('%',#{string},'%') or author like concat('%',#{string},'%')
    </select>

concat() 函数,是用来连接字符串。在实际的使用中,条件是作为参数传递进来的,所以我们使用 concat() 函数

测试

//模糊查询
List<Article> as = session.selectList("listArticleFuzzy","东野");
for(Article a:as){
System.out.println(a.toString());
}

打印输出
1-白夜行-东野圭吾

  1. 多条件查询
    如果我们又要限定查询的id,又要模糊查询,就需要传两个参数

Mapper

<select id="listArticleByIdAndStr" parameterType="map" resultType="Article">
select * from article where id > #{id} and title like concat('%',#{string},'%')
</select>

这里我们传入的参数类型事map

测试

Map<String,Object>params = new HashMap<>();
params.put("id",0);
params.put("string","白夜");
List<Article> as = session.selectList("listArticleByIdAndStr",params);
for(Article a:as){
System.out.println(a.toString());
}

当put的id数值0时能查询到‘白夜行’,更改为0以上则不能查询到。语句正确

2.3 联合查询

  1. 一对多 一个作者有多本著作
    增加author表
    create table author(
    id int NOT NULL AUTO_INCREMENT,
    name VARCHAR(30) DEFAULT NULL,
    PRIMARY KEY(id)
    )AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

修改article表,将author属性改为author_id,数据类型也改为int,并且增加外键关联
当初一开始没想这么多现在改的好傻逼

alter table article add constraint FK_arToau foreign key(author_id) REFERENCES author(id)

插入数据

INSERT INTO author VALUES(null,'东野圭吾')
INSERT INTO author VALUES(null,'江南')
INSERT INTO author VALUES(null,'伊坂幸太郎')

article中在随便插入测试数据

增加Author Pojo 属性中多了一个集合属性

package com.x2y.pojo;

import java.util.List;

public class Author {
private int aid;
private String aname;
List<Article> articles;
public int getAid() {
return aid;
}

public void setAid(int aid) {
this.aid = aid;
}

public String getAname() {
return aname;
}

public void setAname(String aname) {
this.aname = aname;
}

public List<Article> getArticles() {
return articles;
}

public void setArticles(List<Article> articles) {
this.articles = articles;
}

@Override
public String toString() {
return "作者id: "+aid+"--"+"作者姓名: "+aname;
}
}

*添加Mapper Author.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.x2y.pojo">
<resultMap id="authorBean" type="Author">
<!-- property:主键在pojo中的属性名 -->
<!-- column:主键在数据库中的列名 -->
<id column="auid" property="aid"/>
<result column="name" property="aname"/>
<!-- 一对多的关系 -->
<!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->
<collection property="articles" ofType="Article">
<id column="arid" property="id"/>
<result column="title" property="title"/>
<result column="author_id" property="author_id"/>
</collection>
</resultMap>

<select id="listAuthorWorks" resultMap="authorBean">
select au.*,ar.*,au.id 'auid',ar.id 'arid'from author au left join article ar on ar.author_id = au.id
</select>
</mapper>

记得在mybatis-config.xml中配置Author.xml
这里用resultMap对查询的结果进行映射。
配置的时候其中column:主键在数据库中的列名 、property:主键在pojo中的属性名

但是这里有一个问题,在数据库中两个表的主键都是id,在查询的时候返回结果集进行匹配的时候就会出问题。
这里我在定义映射集的时候把Author的主键定义为column="auid" property="aid"对应arthor pojo中的aid,Article的主键定义为 column="arid" property="id"对应artice pojo中的id,在<collection>中配置的就是Article集合的映射。

这样就比较好理解sql语句了,分别将查询结果author.id命名为auid article.id命名为arid来与映射配置对应。

select au.*,ar.*,au.id 'auid',ar.id 'arid'from author au left join article ar on ar.author_id = au.id

测试

List<Author>authors = session.selectList("listAuthorWorks");
for (Author au : authors) {
System.out.println(au);
List<Article> articles = au.getArticles();
for (Article ar : articles) {
System.out.println("\t"+ar);
}
}

输出

作者id: 1--作者姓名: 东野圭吾
1-白夜行-1
4-嫌疑人X的献身-1
5-解忧杂货铺-1
作者id: 2--作者姓名: 江南
2-龙族-2
6-九州缥缈录-2
作者id: 3--作者姓名: 伊坂幸太郎
7-金色梦乡-3
  1. 多对一 多本著作是一个作者所写

修改article pojo 增加author属性

private Author author;

public Author getAuthor() {
return author;
}

public void setAuthor(Author author) {
this.author = author;
}

Article.xml中增加相关映射配置和查询语句

<resultMap type="Article" id="articleBean">
<id column="arid" property="id"/>
<result column="title" property="title"/>
<result column="author_id" property="author_id"/>

<!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
<association property="author" javaType="Author">
<id column="auid" property="aid"/>
<result column="name" property="aname"/>
</association>
</resultMap>

<!-- 根据id查询Product, 关联将Orders查询出来 -->
<select id="listArticleAndAuthor" resultMap="articleBean">
select ar.*,au.*,ar.id 'arid',au.id 'auid' from article ar left join author au on ar.author_id = au.id
</select>

基本上和一对多的查询是相似的配置,区别在于这里用的是进行关联

测试

List<Article> articles = session.selectList("listArticleAndAuthor");
for(Article ar: articles){
System.out.println(ar+" ----》 \t "+ ar.getAuthor());
}

输出

1-白夜行-1 ----》 	 作者id: 1--作者姓名: 东野圭吾
4-嫌疑人X的献身-1 ----》 作者id: 1--作者姓名: 东野圭吾
5-解忧杂货铺-1 ----》 作者id: 1--作者姓名: 东野圭吾
2-龙族-2 ----》 作者id: 2--作者姓名: 江南
6-九州缥缈录-2 ----》 作者id: 2--作者姓名: 江南
7-金色梦乡-3 ----》 作者id: 3--作者姓名: 伊坂幸太郎
  1. 多对多 比如一个收藏夹可以有多本书,一本书可以存在多个收藏夹。

新建收藏夹表

CREATE TABLE  favorites (
id int (11) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) DEFAULT NULL,
PRIMARY KEY(id)
)AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO favorites VALUES(1,"我的最爱");
INSERT INTO favorites VALUES(2,"必读经典");

为了维系多对多关系,必须要一个中间表。 在这里我们新建(FavoritesItem)表来作为中间表

CREATE TABLE  favorites_items (
id int (11) NOT NULL AUTO_INCREMENT,
fid int,
arid int,
PRIMARY KEY(id)
)AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO favorites_items VALUES(null,1,1);
INSERT INTO favorites_items VALUES(null,1,2);
INSERT INTO favorites_items VALUES(null,1,4);
INSERT INTO favorites_items VALUES(null,2,2);
INSERT INTO favorites_items VALUES(null,2,4);
INSERT INTO favorites_items VALUES(null,2,5);

创建对应pojo类 首先是Favorites

package com.x2y.pojo;

import java.util.List;

public class Favorites {
private int fid;
private String fname;
List<FavoritesItems>favoritesItems;

public int getFid() {
return fid;
}

public void setFid(int fid) {
this.fid = fid;
}

public String getFname() {
return fname;
}

public void setFname(String fname) {
this.fname = fname;
}

public List<FavoritesItems> getFavoritesItems() {
return favoritesItems;
}

public void setFavoritesItems(List<FavoritesItems> favoritesItems) {
this.favoritesItems = favoritesItems;
}
}

收藏项FavoritesItems

package com.x2y.pojo;

public class FavoritesItems {
private int fiid;
private Favorites favorites;
private Article article;

public int getFiid() {
return fiid;
}

public void setFiid(int fiid) {
this.fiid = fiid;
}

public Favorites getFavorites() {
return favorites;
}

public void setFavorites(Favorites favorites) {
this.favorites = favorites;
}

public Article getArticle() {
return article;
}

public void setArticle(Article article) {
this.article = article;
}
}

增加Mapper Favorites.xml并且将之配置入mybatis-config

<?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.x2y.pojo">
<resultMap id="favoritesBean" type="Favorites">
<id column="fid" property="fid"/>
<result column="fname" property="fname"/>

<collection property="favoritesItems" ofType="FavoritesItems">
<id column="fiid" property="fiid"/>
<association property="article" javaType="Article">
<id column="arid" property="id"/>
<result column="title" property="title"/>
<result column="author_id" property="author_id"/>
</association>
</collection>
</resultMap>

<select id="listFavorites" resultMap="favoritesBean">
select ar.*,f.id 'fid',f.name 'fname',fi.id 'fiid',ar.id 'arid'
from favorites f
left join favorites_items fi on f.id = fi.fid
left join article ar on fi.arid = ar.id
</select>

<select id="getFavorites" parameterType="int" resultMap="favoritesBean">
select ar.*,f.id 'fid',f.name 'fname',fi.id 'fiid',ar.id 'arid'


from favorites f
left join favorites_items fi on f.id = fi.fid
left join article ar on fi.arid = ar.id
where f.id= #{id}
</select>
</mapper>

这里写了两个语句,一个是罗列全部收藏夹,一个是罗列指定id的
主要就是3个表的联合查询,在映射上嵌套有点复杂了,其他就没什么,和前面的差别不大

测试

List<Favorites> favorites = session.selectList("listFavorites");
for(Favorites fa :favorites) {
System.out.println(fa.getFname());
List<FavoritesItems> favoritesItems = fa.getFavoritesItems();
for (FavoritesItems fai : favoritesItems){
System.out.format("\t%d\t%s\t%d%n",fai.getArticle().getId(),fai.getArticle().getTitle(),fai.getArticle().getAuthor_id());
}
}

输出结果

我的最爱
1 白夜行 1
2 龙族 2
4 嫌疑人X的献身 1
必读经典
2 龙族 2
4 嫌疑人X的献身 1
5 解忧杂货铺 1

ok

2.4 动态SQL

  • if

动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如说就在上面多对多的sql语句中,我写了两个查询收藏夹的SQL,显得臃肿,重合的代码太多了。

现在改写

<select id="listFavorites" resultMap="favoritesBean">
select ar.*,f.id 'fid',f.name 'fname',fi.id 'fiid',ar.id 'arid'
from favorites f
left join favorites_items fi on f.id = fi.fid
left join article ar on fi.arid = ar.id
<if test="id!=null">
where f.id = #{id}
</if>
</select>

测试

Map<String,Object> params = new HashMap<>();
params.put("id",1);
List<Favorites> favorites = session.selectList("listFavorites",params);

for(Favorites fa :favorites) {
System.out.println(fa.getFname());
List<FavoritesItems> favoritesItems = fa.getFavoritesItems();
for (FavoritesItems fai : favoritesItems){
System.out.format("\t%d\t%s\t%d%n",fai.getArticle().getId(),fai.getArticle().getTitle(),fai.getArticle().getAuthor_id());
}
}

这里要注意的是,在selectList传参数的时候,第二个默认传的是Object类型的数据,这里传了一个Map对象进去。

如果直接写成这样session.selectList("listFavorites",1);
会报错There is no getter for property named 'id' in 'class java.lang.Integer'意思就是没有发现id属性的getter方法。

但是如果我们就是要用这种直接传参呢,也是可以的,不过要修改SQL语句

  1. 使用_parameter

    <select id="listFavorites" parameterType="int" resultMap="favoritesBean">
    select ar.*,f.id 'fid',f.name 'fname',fi.id 'fiid',ar.id 'arid'
    from favorites f
    left join favorites_items fi on f.id = fi.fid
    left join article ar on fi.arid = ar.id
    <if test="_parameter!=null">
    where f.id = #{id}
    </if>
    </select>

    将if 判断中的参数换为_parameter

  2. 使用mybatis默认的对象名:value
    <if test="value!=null">也就行了

输出结果

我的最爱
1 白夜行 1
2 龙族 2
4 嫌疑人X的献身 1
  • trim, where, set

上面用if时我们只是单条件查询,如果我们改成多条件查询,比如编号大于某数和根据收藏夹名字模糊查询

<select id="listFavoritesBy"  resultMap="favoritesBean">
select ar.*,f.id 'fid',f.name 'fname',fi.id 'fiid',ar.id 'arid'
from favorites f
left join favorites_items fi on f.id = fi.fid
left join article ar on fi.arid = ar.id
<if test="id!=null">
where f.id > #{id}
</if>
<if test="name!=null">
and f.name like concat('%',#{name},'%')
</if>
</select>

当两个参数都有或者只有第一个参数的时候是没有问题的,但是如果只传入第二个参数,那么拼接成错误的sql语句。
select * from table and这种错误sql等等。

现在改写一下,很简单标签包裹一下标签**就ok了

<select id="listFavoritesByWhere"  resultMap="favoritesBean">
select ar.*,f.id 'fid',f.name 'fname',fi.id 'fiid',ar.id 'arid'
from favorites f
left join favorites_items fi on f.id = fi.fid
left join article ar on fi.arid = ar.id
<where>
<if test="id!=null">
f.id > #{id}
</if>
<if test="name!=null">
and f.name like concat('%',#{name},'%')
</if>
</where>
</select>

这样就可以避免参数顺序拼接出错了。
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where_ 元素也会将它们去除。

set标签和where标签的功能类似,只不过set是用于动态更新(update),set元素可以用于动态包含需要更新的列,而舍去其它的。
这里用官方文档给的例子

<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>

set元素会动态前置 SET 关键字,同时也会删掉无关的逗号。

trim
用来定制想要的功能
比如等价于

<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>

prefixOverrides属性会忽略通过管道分隔的文本序列,作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。

等价于

<trim prefix="SET" suffixOverrides=",">
...
</trim>

这里删去的是后缀值,同时添加了前缀值。

  • choose, when, otherwise

有时我们不想应用到所有的条件语句,而只想从中择其一项,就有了Choose (类似 Java 中的 switch 语句。)

改写查询收藏夹的语句

<select id="listFavoritesByChoose"  resultMap="favoritesBean">
select ar.*,f.id 'fid',f.name 'fname',fi.id 'fiid',ar.id 'arid'
from favorites f
left join favorites_items fi on f.id = fi.fid
left join article ar on fi.arid = ar.id
where
<choose>
<when test="id!=null">
f.id = #{id}
</when>
<when test="name!=null">
f.name like concat('%',#{name},'%')
</when>
<otherwise>
f.id > 0
</otherwise>
</choose>
</select>

choose只用一个限定条件,这里的意思就是传参是 id 就更具 id 查询,如果传的是名称就根据名称模糊查询,没有给条件就默认查询所有收藏夹。

  • foreach

用于对一个集合进行遍历,通常是在构建 IN 条件语句的时候。

比如我们查询article表,根据指定的 id 集合查询

<select id="listArticleByList" resultType="Article">
select * from article where id in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>

这里我们查询 1 2 4

List<Integer> articleList = new ArrayList<>();
articleList.add(1);
articleList.add(2);
articleList.add(4);

List<Article> as = session.selectList("listArticleByList",articleList);
for(Article a:as){
System.out.println(a.toString());
}

输出

1-白夜行-1
2-龙族-2
4-嫌疑人X的献身-1

ok

  • bind
    bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。

用处就是提高了代码的可以执行,比如模糊查询
MySQL数据库,常常用到的是一个concat,它用’%’和参数相连。然而在Oracle数据库则没有,Oracle数据库用连接符号”||“。

<select id="listArticleFuzzy" resultType="Article">
select * from article where title like concat('%',#{string},'%')
</select>

这是Mysql数据库的语句,若是换成Oracle数据库
那么语句应该是
select * from article where title like '%'``||#{``string``}||``'%'

但是用元素可以解决这种问题
改写成

<select id="listArticleFuzzy" resultType="Article">
<bind name="liketitle" value="'%' + name + '%'" />
select * from product_ where name like #{liketile}
</select>

最后乱七八糟的附上代码
oTATo
https://github.com/xxysama/mybatis_demo