目录
第一章: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接口
package com.qcby.mapper;import com.qcby.domain.User;import java.util.List;public interface UserMapper {//条件查询public List<User> findByWhere(User user);
}
UserMapper.xml配置文件
<!-- 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>
测试方法
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标签的外面
<!-- 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类中添加属性
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接口中添加方法
public List<User> findByIds(User user);
4.配置文件
<!-- 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.测试方法
//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.配置文件编写
<!--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
<!-- 提取公共的SQL -->
<sql id="findAllSql">select * from user
</sql>
在查询中引用公共SQL
<select id="findAll" resultType="com.qcby.domain.User"><include refid="findAllSql"/>/*select * from user*/
</select>
定义分页模板
<sql id="pagination">limit #{start}, #{size}
</sql>
在分页查询中使用
<select id="findUsersWithPagination" resultType="com.qcby.domain.User">select<include refid="baseColumns"/>from user<include refid="userConditions"/><include refid="pagination"/>
</select>
动态生成SQL:
select id, username, birthday, sex, address from user limit 5, 5
第二章:多表查询
1. 多表设计
1.一对一 其实一对一可以设计成一张表结构
2.一对多 再一的一方添加多的一方的集合属性
3.多对一 在多的一方添加一的对象属性
4.多对多 在要查询的实体类中加入对方的集合属性。通过中间表,三表联查
2.搭建开发的环境
建表语句
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类
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接口
package com.qcby.mapper;public interface AccountMapper {
}
编写AccountMapper.xml的配置文件
<?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>
主配置文件中引入映射配置文件
<!-- 加载映射的配置文件 -->
<mappers><mapper resource="com/qcby/mapper/UserMapper.xml"/><mapper resource="com/qcby/mapper/AccountMapper.xml"/>
</mappers>
3.多对一查询(一对一查询)
1.需求:查询的数据中包含account所有的字段,再包含用户的名称和地址
2.在Account类中添加user的属性,表示该帐户只属于这个用户
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接口中编写查询的方法
package com.qcby.mapper;import com.qcby.domain.Account;import java.util.List;public interface AccountMapper {public List<Account> findAll();
}
4.编写配置文件
<?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.测试方法
//多对一查询
@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的属性
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接口中定义方法
//查询一对多
public List<User> findOneToMany();
4.编写配置文件
<!-- 一对多查询 -->
<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.测试方法
//一对多查询
@Test
public void testOneToManyTest() throws Exception{List<User> list = mapper.findOneToMany();//遍历list集合for(User user : list){System.out.println(user);}
}
5.多对多查询
1.创建表
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
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.编写接口
package com.qcby.mapper;import com.qcby.domain.Role;import java.util.List;public interface RoleMapper {public List<Role> findAll();
}
4.编写配置文件
<?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.编写测试方法
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);}}
}