Mybatis---MyBatis映射文件SQL深入、多表查询

server/2024/11/28 7:02:41/

目录

第一章:MyBatis映射文件SQL深入

1.动态SQL 语句之if标签

2. 动态SQL语句之where标签

3. 动态SQL语句之foreach标签

4. 提取公用的SQL语句

提取公用SQL片段

定义分页模板

第二章:多表查询

1. 多表设计

2.搭建开发的环境

3.多对一查询(一对一查询)

4.一对多查询

5.多对多查询


第一章:MyBatis映射文件SQL深入

1.动态SQL 语句之if标签

UserMapper接口

java">package com.qcby.mapper;import com.qcby.domain.User;import java.util.List;public interface UserMapper {//条件查询public List<User> findByWhere(User user);
}

UserMapper.xml配置文件

java"><!-- if标签 -->
<select id="findByWhere" parameterType="com.qcby.domain.User" resultType="com.qcby.domain.User">select * from user where 1 = 1<if test="username !=null and username != ''">and username like #{username}</if><if test="sex !=null and sex != ''">and sex like #{sex}</if>
</select>

测试方法

java">package com.qcby.mapper;import com.qcby.domain.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;public class UserTest {private InputStream in;private SqlSession session;private UserMapper mapper;@Beforepublic void init() throws Exception{//加载配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");// 创建工厂对象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);// 创建Session对象session = factory.openSession();// 获取到代理对象mapper = session.getMapper(UserMapper.class);}@Afterpublic void destory() throws IOException {in.close();session.close();}//条件查询(if标签/where标签)@Testpublic void findByWhereTest() throws Exception{User user = new User();user.setUsername("%熊%");user.setSex("女");List<User> list = mapper.findByWhere(user);for(User user1 : list){System.out.println(user1);}
}

2. 动态SQL语句之where标签

1.where标签目的就是为了去掉 where 1=1的拼接的
2.where标签使用在if标签的外面

java"><!-- where标签 自动处理开头的 AND 或 OR -->
<select id="findByWhere" parameterType="com.qcby.domain.User" resultType="com.qcby.domain.User">select * from user<where><if test="username !=null and username != ''">and username like #{username}</if><if test="sex !=null and sex != ''">and sex like #{sex}</if></where>
</select>

测试方法和使用if标签测试方法相同

3. 动态SQL语句之foreach标签

两种SQL语句

第一种

1.需求的SQL语句:select * from user where id = 1 or id = 2 or id = 3

2.在User类中添加属性

java">package com.qcby.domain;import java.io.Serializable;
import java.util.Date;
import java.util.List;public class User implements Serializable{private Integer id;private String username;private Date birthday;private String sex;private String address;//演示foreach标签private List<Integer> ids;//get和set方法
}

3.在UserMapper接口中添加方法

java">public List<User> findByIds(User user);

4.配置文件

java"><!-- foreach标签 select * from user where id = 1 or id = 2 or id = 3 -->
<select id="findByIds" parameterType="com.qcby.domain.User" resultType="com.qcby.domain.User">select * from user<where><!--open 表示在集合中的第一个元素前加上 id = ,separator 表示在每个元素之间用 or id = 分隔。--><foreach collection="ids" open="id = " separator="or id = " item="i">#{i}</foreach></where>
</select>

collection="ids"

        指定要遍历的集合,ids是User 对象中的一个属性。

item="i":

        每次遍历的元素赋值给i。

5.测试方法

java">//foreach标签
@Test
public void findByIdsTest() throws Exception{User user = new User();//创建User对象List<Integer> ids = new ArrayList<>();ids.add(1);//添加要查询的idids.add(2);ids.add(3);user.setIds(ids);//将集合设置到user对象中List<User> list = mapper.findByIds(user);for(User user1 : list){System.out.println(user1);}
}

第二种

1.需求SQL:select * from user where id in (1,2,3)
2.配置文件编写

java"><!--foreach标签 select * from user where id in (1,2,3)-->
<select id="findByIds" parameterType="com.qcby.domain.User" resultType="com.qcby.domain.User">select * from user<where><foreach collection="ids" open="id in (" separator="," close=")" item="i">#{i}</foreach></where>
</select>

open="id in ("

        在遍历的第一个元素前追加 id in (

separator=","

        在每个元素之间插入 , ,用来连接多个条件。

close=")"

        在遍历的最后一个元素后追加 )

4. 提取公用的SQL语句

        为了避免SQL的重复编写和维护困难,MyBatis 提供了提取和复用 SQL 语句的功能,可以将公共的 SQL 片段提取出来,通过引用的方式在不同的 SQL 中复用。

提取公用SQL片段

使用标签定义公共SQL

  • MyBatis 提供了 标签,用于定义可以复用的 SQL 片段。
  • 通过 标签引用该 SQL 片段。

定义公共SQL

java"><!-- 提取公共的SQL -->
<sql id="findAllSql">select * from user
</sql>

在查询中引用公共SQL

java"><select id="findAll" resultType="com.qcby.domain.User"><include refid="findAllSql"/>/*select * from user*/
</select>

定义分页模板

java"><sql id="pagination">limit #{start}, #{size}
</sql>

在分页查询中使用

java"><select id="findUsersWithPagination" resultType="com.qcby.domain.User">select<include refid="baseColumns"/>from user<include refid="userConditions"/><include refid="pagination"/>
</select>

动态生成SQL:

java">select id, username, birthday, sex, address from user limit 5, 5

第二章:多表查询

1. 多表设计

1.一对一        其实一对一可以设计成一张表结构
2.一对多        再一的一方添加多的一方的集合属性
3.多对一         在多的一方添加一的对象属性
4.多对多        在要查询的实体类中加入对方的集合属性。通过中间表,三表联查

2.搭建开发的环境

建表语句

java">CREATE TABLE `user` (`id` int(11) NOT NULL auto_increment,`username` varchar(32) NOT NULL COMMENT '用户名称',`birthday` datetime default NULL COMMENT '生日',`sex` char(1) default NULL COMMENT '性别',`address` varchar(256) default NULL COMMENT '地址',PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
​
insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'老王','2018-02-27 17:47:08','男','北京'),(2,'熊大','2018-03-02 15:09:37','女','上海'),(3,'熊二','2018-03-04 11:34:34','女','深圳'),(4,'光头强','2018-03-04 12:04:06','男','广州');
​
CREATE TABLE `account` (`ID` int(11) NOT NULL COMMENT '编号',`UID` int(11) default NULL COMMENT '用户编号',`MONEY` double default NULL COMMENT '金额',PRIMARY KEY  (`ID`),KEY `FK_Reference_8` (`UID`),CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
​
insert  into `account`(`ID`,`UID`,`MONEY`) values (1,1,1000),(2,2,1000),(3,2,2000);

编写Account的JavaBean类

java">package com.qcby.domain;import java.io.Serializable;/*** 账号*/
public class Account implements Serializable{private Integer id;private Integer uid;private Double money;
​public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getUid() {return uid;}public void setUid(Integer uid) {this.uid = uid;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}
}

编写AccountMapper接口

java">package com.qcby.mapper;public interface AccountMapper {
}

编写AccountMapper.xml的配置文件

java"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qcby.mapper.AccountMapper"></mapper>

主配置文件中引入映射配置文件

java"><!-- 加载映射的配置文件 -->
<mappers><mapper resource="com/qcby/mapper/UserMapper.xml"/><mapper resource="com/qcby/mapper/AccountMapper.xml"/>
</mappers>

3.多对一查询(一对一查询)

1.需求:查询的数据中包含account所有的字段,再包含用户的名称和地址

2.在Account类中添加user的属性,表示该帐户只属于这个用户

java">package com.qcby.domain;import java.io.Serializable;/*** 账号*/
public class Account implements Serializable{private Integer id;private Integer uid;private Double money;//用户private User user;public Account(Integer id, Integer uid, Double money, User user) {this.id = id;this.uid = uid;this.money = money;this.user = user;}public Account() {}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getUid() {return uid;}public void setUid(Integer uid) {this.uid = uid;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}@Overridepublic String toString() {return "Account{" +"id=" + id +", uid=" + uid +", money=" + money +", user=" + user +'}';}
}

3.在AccountMapper接口中编写查询的方法

java">package com.qcby.mapper;import com.qcby.domain.Account;import java.util.List;public interface AccountMapper {public List<Account> findAll();
}

4.编写配置文件

java"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qcby.mapper.AccountMapper"><!-- 内连接查询 --><select id="findAll" resultMap="accountMap">select a.*,u.username,u.address from account a,user u where a.uid = u.id</select><!-- 进行数据封装--><resultMap id="accountMap" type="com.qcby.domain.Account"><result property="id" column="id"/><result property="uid" column="uid"/><result property="money" column="money"/><!--property:设置需要处理映射关系的属性的属性名column:设置要处理映射关系的属性对应的列名javaType:设置要处理的属性的类型--><!-- <association> 标签:一对一关系 --><association property="user" javaType="com.qcby.domain.User"><result property="username" column="username"/><result property="address" column="address"/></association></resultMap>
</mapper>

5.测试方法

java">//多对一查询
@Test
public void findAllTest() throws Exception{List<Account> list = mapper.findAll();for(Account accout : list){System.out.println(accout);}
}

4.一对多查询

1.如果想查询 select u.*,a.money from user u left join account a on u.id = a.uid 语句的内容

2.在User类中添加List的属性

java">package com.qcby.domain;import java.io.Serializable;
import java.util.Date;
import java.util.List;public class User implements Serializable{private Integer id;private String username;private Date birthday;private String sex;private String address;//演示foreach标签private List<Integer> ids;//演示一对多查询private List<Account> accounts;public User(Integer id, String username, Date birthday, String sex, String address, List<Integer> ids, List<Account> accounts) {this.id = id;this.username = username;this.birthday = birthday;this.sex = sex;this.address = address;this.ids = ids;this.accounts = accounts;}public User() {}public List<Account> getAccounts() {return accounts;}public void setAccounts(List<Account> accounts) {this.accounts = accounts;}public List<Integer> getIds() {return ids;}public void setIds(List<Integer> ids) {this.ids = ids;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", birthday=" + birthday +", sex='" + sex + '\'' +", address='" + address + '\'' +", ids=" + ids +", accounts=" + accounts +'}';}
}

3.在UserMapper接口中定义方法

java">//查询一对多
public List<User> findOneToMany();

4.编写配置文件

java"><!-- 一对多查询 -->
<select id="findOneToMany" resultMap="userMap">select u.*,a.money from user u left join account a on u.id = a.uid
</select><resultMap id="userMap" type="com.qcby.domain.User"><result property="id" column="id"/><result property="username" column="username"/><result property="birthday" column="birthday"/><result property="address" column="address"/><!--ofType 属性用于指定集合中的每个元素的 Java 类型。用于处理一对多--><collection property="accounts" ofType="com.qcby.domain.Account"><result property="money" column="money"/></collection>
</resultMap>

5.测试方法

java">//一对多查询
@Test
public void testOneToManyTest() throws Exception{List<User> list = mapper.findOneToMany();//遍历list集合for(User user : list){System.out.println(user);}
}

5.多对多查询

1.创建表

java">CREATE TABLE `role` (`ID` int(11) NOT NULL COMMENT '编号',`ROLE_NAME` varchar(30) default NULL COMMENT '角色名称',`ROLE_DESC` varchar(60) default NULL COMMENT '角色描述',PRIMARY KEY  (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
​
insert  into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (1,'组长','管理整个组'),(2,'班主任','管理整个班级'),(3,'校长','管理整个学校');
​
CREATE TABLE `user_role` (`UID` int(11) NOT NULL COMMENT '用户编号',`RID` int(11) NOT NULL COMMENT '角色编号',PRIMARY KEY  (`UID`,`RID`),KEY `FK_Reference_10` (`RID`),CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
​
insert  into `user_role`(`UID`,`RID`) values (1,1),(1,2),(2,2);

2.编写JavaBean

java">package com.qcby.domain;import java.io.Serializable;
import java.util.List;public class Role implements Serializable{private Integer id;private String role_name;private String role_desc;private List<User> users;public Role(Integer id, String role_name, String role_desc, List<User> users) {this.id = id;this.role_name = role_name;this.role_desc = role_desc;this.users = users;}public List<User> getUsers() {return users;}public void setUsers(List<User> users) {this.users = users;}public Role() {}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getRole_name() {return role_name;}public void setRole_name(String role_name) {this.role_name = role_name;}public String getRole_desc() {return role_desc;}public void setRole_desc(String role_desc) {this.role_desc = role_desc;}@Overridepublic String toString() {return "Role{" +"id=" + id +", role_name='" + role_name + '\'' +", role_desc='" + role_desc + '\'' +", users=" + users +'}';}
}

3.编写接口

java">package com.qcby.mapper;import com.qcby.domain.Role;import java.util.List;public interface RoleMapper {public List<Role> findAll();
}

4.编写配置文件

java"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qcby.mapper.RoleMapper"><select id="findAll" resultMap="roleMap">select r.*,u.username from user u,user_role ur,role r where u.id = ur.UID and ur.RID = r.ID</select><resultMap id="roleMap" type="role"><id property="id" column="id"/><result property="role_name" column="role_name"/><result property="role_desc" column="role_desc"/><collection property="users" ofType="com.qcby.domain.User"><result property="username" column="username"/></collection></resultMap>
</mapper>

5.编写测试方法

java">package com.qcby.mapper;import com.qcby.domain.Account;
import com.qcby.domain.Role;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;import javax.swing.tree.RowMapper;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class Test03 {private InputStream in;private SqlSession session;private RoleMapper mapper;@Beforepublic void init() throws Exception{//加载配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");// 创建工厂对象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);// 创建Session对象session = factory.openSession();// 获取到代理对象mapper = session.getMapper(RoleMapper.class);}@Afterpublic void destory() throws IOException {in.close();session.close();}//多对多查询@Testpublic void findAllTest() throws Exception{List<Role> list = mapper.findAll();for(Role role : list){System.out.println(role);}}
}

http://www.ppmy.cn/server/145558.html

相关文章

关于按天切割Tomcat的catalina.out日志文件的配置

1、catalina.out 是 Tomcat 的标准输出和标准错误日志&#xff0c;通常输出到 Tomcat 安装目录下的 logs 文件夹中。这个日志文件会记录 Tomcat 启动、停止以及运行过程中产生的所有日志信息。 2、在Apache Tomcat中&#xff0c;日志文件catalina.out默认情况下不会自动按天切割…

.NET9 - Swagger平替Scalar详解(四)

书接上回&#xff0c;上一章介绍了Swagger代替品Scalar&#xff0c;在使用中遇到不少问题&#xff0c;今天单独分享一下之前Swagger中常用的功能如何在Scalar中使用。 下面我们将围绕文档版本说明、接口分类、接口描述、参数描述、枚举类型、文件上传、JWT认证等方面详细讲解。…

Kubernetes 还是 SpringCloud?

前些年&#xff0c;随着微服务的概念提出以及落地&#xff0c;不断有很多的公司都加入到了这场技术革新中&#xff0c;现在可谓是人人都在做和说微服务。 提到微服务&#xff0c;Java栈内&#xff0c;就不得不提SpringBoot、SpringCloud、Dubbo。 近几年&#xff0c;随着Cloud …

远离网上的广告和无用信息,自己动手搭建Tipask问答网站

文章目录 前言1.Tipask网站搭建1.1 Tipask网站下载和安装1.2 Tipask网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试4. 结语 前…

C++——多态(下)

目录 引言 多态 4.多态的原理 4.1 虚函数表指针 4.2 多态的原理 5.单继承和多继承关系的虚函数表 5.1 单继承中的虚函数表 5.2 多继承中的虚函数表 结束语 引言 接下来我们继续学习多态。 没有阅读多态&#xff08;上&#xff09;的可以点击下面的链接哦~ C——多态…

RabbitMQ的预取值详解

RabbitMQ的预取值&#xff08;Prefetch Value&#xff09;是一个关键概念&#xff0c;它决定了消费者在从队列中获取消息时&#xff0c;一次性可以获取的消息数量。这一机制对于优化消息分发和消费者的负载均衡至关重要。 什么是RabbitMQ的预取值&#xff1f; 预取值是指消费者…

前端项目的动态路由实现(vue)

一、引言 动态路由&#xff0c;很多场景是&#xff0c;有些页面必须是某些用户或者某些角色才能访问&#xff0c;所以呢&#xff0c;前端的代码即使不给页面的入口&#xff0c;但是要是直接在地址栏敲入相关地址页面还是可以被访问到。为了杜绝这种情况&#xff0c;就用到了动…

表的操作DDL

创建表 character set 字符集 collate 校验规则 engine 存储引擎;属性要用 ‘,’ 隔开&#xff0c;最后一个属性不加 ‘,’ &#xff0c;不要忘了括号其中charset utf8 collate utf8_general_ci engine MyIsam;可以不写 create database usr_db; use usr_db; //创建表 user1 c…