我们需要传入查询条件,假如我们希望传入用户名,返回用户信息。
xml:
我们通过使用#{xxx}
或是${xxx}
来填入我们给定的属性,实际上Mybatis本质也是通过PreparedStatement
首先进行一次预编译,有效地防止SQL注入问题,但是如果使用${xxx}
就不再是通过预编译,而是直接传值,因此我们一般都使用#{xxx}
来进行操作。
接口:
public interface UserMapper {
List selectByUsername(String username);
}
xml:
insert into accounting_ledger.user(username, password) VALUES (#{username},#{password})
接口:
package Mybatis.Mapper;
import Mybatis.User;
import java.util.List;
public interface UserMapper {
List selectUser();
List selectByUsername(String username);
int insertUser(User user);
}
调用这个方法:
User user3=new User();
user3.setPassword("password");
user3.setUsername("lyj不做饭");
int i=testMapper.insertUser(user3);
System.out.println(i);
我们发现虽然xml语句中有两个接受的参数,但是我们在接口中可以直接传入user类,而不必把user分解为两个字段。所以显然mybatis为我们自动分解了。
由于我们并没有指定如何分解user类,而默认的分解方式是根据字段的名字对应的。也就是说我们要保证
VALUES (#{username},#{password})
和user类的字段名称相同。
考虑如下情况:
目前3个表:老师表(tid,tname),学生表(sid,sname),课程表(tid,sid)
目标是选择出老师1号的所有学生。所以我们通过tid链接老师和课程表,通过sid链接学生表和课程表,然后把老师1号上的课程的所有学生选择出来即可。
首先我们的老师类定义如下:
@Data
public class Teacher {
int tid;
String name;
List studentList;
}
选择出来的学生会存放到student list中。
这样的复杂查询需要我们自己指定映射规则,我们来看xml语句:
1.先看
举例,sql语句返回了(1)tid=1,name=lyj,sid=1 (2)tid=1,name=lyj,sid=2
这时由于(1)(2)两条语句的tid是一样的,第二条语句的sid就会自动成为lyj老师对象下studentlist里的第二个元素。
同样的情况,如果用的是
这里的id字段相当于sql语句里的groupby。
2.再看这一段
这里实际上就是在规定当我们的sql读取到和学生相关的字段时,如何映射为java中studentlist里的对象。
通过使用collection来表示将得到的所有和学生相关的结果合并为一个集合 。property="studentList"指定了往哪个集合里丢。
ofType="Student"表明集合中的元素是student。
了解了一对多,那么多对一(sql返回了多个字段,都属于java中的某一个字段)又该如何查询呢,比如每个学生都有一个对应的老师,现在Student新增了一个Teacher对象,那么现在又该如何去处理呢?
@Data
@Accessors(chain = true)
public class Student {
private int sid;
private String name;
private String sex;
private Teacher teacher;
}
@Data
public class Teacher {
int tid;
String name;
}
现在我们希望的是,每次查询到一个Student对象时都带上它的老师:
通过使用association
进行关联,将sql返回的和老师有关的字段全都映射到teacher类上。
动态 SQL 是 MyBatis 中的一项强大功能,它允许在 SQL 映射文件中根据条件来动态生成 SQL 语句。这样可以根据不同的情况灵活地构建不同的 SQL 查询。
假设有一个数据库表 blog
包含以下字段:
id
(INT)title
(VARCHAR)content
(VARCHAR)state
(VARCHAR)我们可以创建一个对应的 Java 类 Blog
来表示这个表的结构:
public class Blog {
private int id;
private String title;
private String content;
private String state;
// 构造方法、getter 和 setter 略...
@Override
public String toString() {
return "Blog{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
", state='" + state + '\'' +
'}';
}
}
xml:
标签用于在生成动态 SQL 时添加 WHERE 子句。它的主要作用是根据条件动态拼接 WHERE 子句,并且在生成的 SQL 语句中会自动去除不必要的 AND 或 OR。
标签包含了两个
子标签,每个
子标签表示一个查询条件。如果条件满足,就会在 WHERE 子句中添加相应的条件语句。
如果传入的参数中 title
和 state
都不为 null 且不为空字符串,那么生成的 SQL 语句为:
SELECT * FROM blog
WHERE title LIKE #{title} AND state = #{state}
只有 title
不为 null 且不为空字符串,那么生成的 SQL 语句可能类似于:
SELECT * FROM blog
WHERE title LIKE #{title}
只有 state
满足条件,生成的 SQL 语句类似于:
SELECT * FROM blog
WHERE state = #{state}
所以上述配置文件背后的逻辑是:
如果传递了 title
参数,并且该参数不为空,则添加 AND title LIKE #{title}
条件,即根据博客标题进行模糊查询。
如果传递了 state
参数,并且该参数不为空,则添加 AND state = #{state}
条件,即根据博客状态进行精确查询。
注意
AND title LIKE #{title}
这里if中的title是传进俩的参数,但是参数不是在后面的 #{title}才被传入的吗?
虽然在执行if语句的时候,还没有执行到 #{title},也就是说如果按照顺序执行,在执行if语句的时候title并没有被赋值,甚至根本不知道title是一个参数。所以这里的逻辑和我们一般认识的编程语言不同。
当解析
标签时,MyBatis 会检查条件表达式中的属性(例如 title
)是否在传递的参数对象中存在,并获取其值。然后,根据这个值来判断是否满足条件,从而决定是否将包含在
标签内的 SQL 语句片段包含在最终的 SQL 语句中。
mybatis还可以生成各种各样的动态sql语句,详情可见动态 SQL_MyBatis中文网