day03 mybatis
<where>
标签
<where>
等同于 where 1=1
<!-- 使用<where>方式-->
select * from user
<where>
<if test="id!=null">
and id=#{id}
</if>
<if test="username!=null">
and username=#{username}
</if>
<if test="password!=null">
and password=#{password}
</if>
</where>
等同于
select * from user where 1=1
<if test="id!=null">
and id=#{id}
</if>
<if test="username!=null">
and username=#{username}
</if>
<if test="password!=null">
and password=#{password}
</if>
动态sql之foreach
需求
传入多个 id 查询用户信息,用下边两个 sql 实现:
SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)
这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。
这样我们将如何进行参数的传递?
UserDao代码添加方法
/**
* 根据多个id进行查询 至于是几个id不确定 可以使用集合 也可以使用数组
* @param ids
* @return
*/
List<User> findInIds(List<Integer> ids);
循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)。
xml文件代码
<!--
foreach:循环标签
collection:表示集合,如果我们的参数使用的是list,那么集合就使用list,如果我们的参数使用的是数组,那么我们就是用array
open="id in (" : 表示sql语句的开始
close=")": 表示sql语句的结束
item="id": 表示存放的变量id
separator="," : 表示以逗号进行分割
include:表示可以包含另外一条sql语句
refid:表示引用 要和引用sql的id保持一致
-->
<select id="findInIds" resultType="user">
<include refid="selectUser"></include>
<where>
<foreach collection="list" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
测试代码
@Test
public void testFindInIds(){
// 动态的传输id数据
List<Integer> list = new ArrayList<Integer>();
list.add(43);
list.add(46);
list.add(48);
List<User> userList = userDao.findInIds(list);
for (User user : userList) {
System.out.println(user);
}
}
运行结果
sql片段抽取
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的
<!--
在同一个类里面,需要查询的表 肯定是一模一样的 如果是一样的话,就可以把表的查询,进行抽取
sql:表示sql语句
id="selectUser":表示唯一标识符,名字随意取
select * from user:表示抽取出来的查询语句
-->
<sql id="selectUser">
select * from user
</sql>
<select id="findInIds" resultType="user">
<include refid="selectUser"></include>
<where>
<foreach collection="list" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
typeHandlers标签
typeHandler 作用
由于Java 类型和数据库的 JDBC 类型不是一一对应的(比如 String 与 varchar), 所以我们把 Java 对象转换为数据库的值,和把数据库的值转换成 Java 对象,需要经过 一定的转换,这两个方向的转换就要用到 TypeHandler,那么有人可能在想了,我们平时没有做任何关于TypeHandler的配置,为什么实体类对象里面的String属性,可以保存成数据库里面的varchar字段或者保存成char字段呢,这是因为MyBatis中已经内置了很多TypeHandler。
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器(截取部分)。
你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个JDBC类型。例如需求:一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来时转换成java的Date,即java的Date与数据库的varchar毫秒值之间转换。
开发步骤:
①定义转换类继承类BaseTypeHandler
②覆盖4个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时 mysql的字符串类型转换成 java的Type类型的方法
③在MyBatis核心配置文件中进行注册
1.创建数据库
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`password` int(11) DEFAULT NULL,
`username` varchar(255) DEFAULT NULL,
`birthday` bigint(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
2.新建模块mybatis-typeHandlers
2.1添加pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu</groupId>
<artifactId>day45mybatis-typeHandlers</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
2.2自定义转换器
package com.atguigu.hander;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
/**
* BaseTypeHandler:表示基本的类型处理器
* <T>:泛型,如果想转换哪个类型 就把泛型给它
*
* 注意:导入date包的时候 导入的是util包 不是sql包
*/
public class MyDateTypeHandler extends BaseTypeHandler<Date> {
/**
* 设置参数 保存数据 调用的是save方法
* @param ps 表示JDBC里面的预处理
* @param i 表示索引 日期的索引位置 在数据库里里面的字段在第4个
* @param date 表示日期
* @param jdbcType
* @throws SQLException
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Date date, JdbcType jdbcType) throws SQLException {
System.out.println("ps = " + ps); // ps = org.apache.ibatis.logging.jdbc.PreparedStatementLogger@4690b489
System.out.println("i = " + i); // i = 3
System.out.println("date = " + date); // date = Mon Nov 07 12:29:59 CST 2022
System.out.println("jdbcType = " + jdbcType); // jdbcType = null
// 获取当前时间
long time = date.getTime();
System.out.println("--------------------");
System.out.println(time);
// 第一个参数:表示索引的位置
// 第二个参数:表示日期的值
ps.setLong(i, time);
}
/**
* 获取结果集
* @param resultSet 表示结果集
* @param s 需要查询列的名字
* @return
* @throws SQLException
*/
@Override
public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
// 需要把数据库里面的数字 转换成日期
System.out.println("find ---> 1");
System.out.println("resultSet = " + resultSet); // resultSet = org.apache.ibatis.logging.jdbc.ResultSetLogger@67a20f67
System.out.println("s = " + s); // s = birthday
long aLong = resultSet.getLong(s);
Date date = new Date(aLong);
return date;
}
@Override
public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
System.out.println("find ---> 2");
return null;
}
@Override
public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
System.out.println("find ---> 3");
return null;
}
}
2.3 在SqlMapConfig.xml配置文件添加自定义类型转换器
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
核心配置文件
表示dtd的约束文件
约束文件的意思:所有的配置都需要放到configuration里面,这个里面需要设置各种属性,大概有十个属性,每个属性是有先后顺序,不能随意放置
所以他的名字叫约束文件
-->
<configuration>
<!-- 设置数据源的属性-->
<properties resource="jdbc.properties"></properties>
<!-- logImpl:表示日志的具体实现
STDOUT:标准输出
LOGGING:日志-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 设置别名-->
<typeAliases>
<!-- 在别名里面设置包名,mybatis会自动的在pojo里面去找他需要的javabean-->
<package name="com.atguigu.pojo"/>
</typeAliases>
<!-- 设置类型处理器-->
<typeHandlers>
<typeHandler handler="com.atguigu.hander.MyDateTypeHandler"></typeHandler>
</typeHandlers>
<!--
配置mybatis的插件 分页插件
ctrl + alt + 空格:自动补全
PageHelper:表示所有的数据库都可以使用这个插件进行分页 需要告知分页插件 我们需要使用哪个数据库进行分页
mysql:表示当前使用的数据库是mysql
-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 设置方言-->
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
<!--
数据源 事物管理器
-->
<!--配置环境变量
environments : 表示设置环境变量,但是环境变量可以设置多个
environment : 表示环境变量
id :表示唯一标示符,随便取名字,想叫什么都可以
default : 表示默认选中哪个环境变量, 注意: 必须跟下面的id保持一致
transactionManager : 表示事物管理器
type="JDBC" : 表示使用JDBC的事物管理器mybatis实际上是对JDBC的封装
MANAGED : 我们自己管理事物
dataSource :表示数据源
type="POOLED" : 表示数据库的连接池
数据源里面需要设置四个参数
驱动,url地址,用户名,密码
UNPOOLED :不适用数据库连接池
JNDI : 只可以跟EJB一起使用
-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--当前的版本 8.0以上,需要设置cj,如果在8.0以下,去掉cj-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
<!--设置URL地址
/// : 这个是主机和端口的缩写
localhost:3306
需要设置时区
北京:东八区,每15度一个区,一个区间隔一个小时
北回归线,广东,广西,云南
时区必须得写,其他的参数可写可不写
useUnicode=true :使用编码格式
characterEncoding=UTF-8 : 编码格式是UTF-8
& :链接符,转义字符 &
get请求:第一个参数 ? 第二个参数:&符号
serverTimezone=Asia/Shanghai ; 使用亚洲上海时区
不要使用UTC
allowPublicKeyRetrieval=true :使用秘钥,使用公钥,只有mysql8.0以上才有
-->
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"></property>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 表示使用配置文件的方式加载crud-->
<mapper resource="com/atguigu/dao/UserDao.xml"></mapper>
</mappers>
</configuration>
2.4 定义javabean
package com.atguigu.pojo;
import java.util.Date;
public class User {
private int id;
private String username;
private String password;
private Date birthday;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday=" + birthday +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
定义UserDao接口
package com.atguigu.dao;
import com.atguigu.pojo.User;
import java.util.List;
public interface UserDao {
void save(User user);
User findUserById(Integer id);
}
2.5 UserDao.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.atguigu.dao.UserDao">
<insert id="save" parameterType="user">
insert into user(username, password, birthday) values(#{username}, #{password}, #{birthday})
</insert>
<select id="findUserById" parameterType="Integer" resultType="user">
select * from user where id=#{id}
</select>
</mapper>
2.6 添加测试操作
package com.atguigu;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.User;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
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.Date;
import java.util.List;
public class MybatisTest {
private UserDao userDao;
private SqlSession sqlSession;
private InputStream is;
@After
public void after() throws Exception{
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
is.close();
}
@Before
public void before() throws IOException {
// 1.需要找到核心配置文件
is = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.构建会话工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 3.读取核心配置文件里面的io流
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
// 4.获取会话对象
sqlSession = sqlSessionFactory.openSession();
// 5.通过会话工厂 获取userdao对象
userDao = sqlSession.getMapper(UserDao.class);
}
@Test
public void testSave(){
User user = new User();
user.setPassword("王五");
user.setPassword("123");
// 类型转换异常 因为pojo里面的日期类型 我们的数据库表里面是一个数据类型
user.setBirthday(new Date());
// 执行保存方法
userDao.save(user);
}
@Test
public void testFindUserById(){
User user = userDao.findUserById(10);
System.out.println(user); // User{id=10, username='null', password='123', birthday=Mon Nov 07 12:25:07 CST 2022}
}
}
plugins标签
MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据
开发步骤:
①导入通用PageHelper的坐标
②在mybatis核心配置文件中配置PageHelper插件
③测试分页数据获取
1.导入通用PageHelper坐标
<!-- 分页助手
github : 表示一个开源的网站
pagehelper : 表示开源网站上面的项目
-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
2.在mybatis核心配置文件中配置PageHelper插件
在sqlMapConfig.xml进行如下配置:
<!--
配置mybatis的插件 分页插件
ctrl + alt + 空格:自动补全
PageHelper:表示所有的数据库都可以使用这个插件进行分页 需要告知分页插件 我们需要使用哪个数据库进行分页
mysql:表示当前使用的数据库是mysql
-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 设置方言-->
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
3.定义接口
List<User> findAll();
4.UserDao.xml
<select id="findAll" resultType="User">
select * from user
</select>
5.分页 测试代码
@Test
public void testFindAll(){
// 开始分页
// 第一个参数:表示 需要查询的是哪个页面
// 第二个参数:表示 每个页面显示几条数据
PageHelper.startPage(1, 2);
List<User> userList = userDao.findAll();
/*for (User user : userList) {
System.out.println("user = " + user);
}*/
PageInfo<User> pageInfo = new PageInfo<>(userList);
System.out.println("总记录数:" + pageInfo.getTotal()); // 总记录数:8
System.out.println("总页数:" + pageInfo.getPages()); // 总页数:4
System.out.println("是否是第一页:" + pageInfo.isIsFirstPage()); // 是否是第一页:true
System.out.println("是否是最后一页:" + pageInfo.isIsLastPage()); // 是否是最后一页:false
}
mybatis多表查询
1.1 一对一查询
1.1.1 一对一查询的模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户
1.1.2 一对一查询的语句
对应的sql语句:select * from orders o,user u where o.uid = u.id;
查询的结果如下:
需求:查询所有订单信息,关联查询下单用户信息
注意:
因为一个订单信息只能供某个用户使用,所以从查询订单信息出发关联查询用户信息为一对一查询。如
果从用户信息出发查询用户下的订单息则为一对多查询,因为一个用户可以有多个订单。
1.1.3 创建项目
项目名字:mybatis-one2many
1.1.4 导入pom坐标
<dependencies>
<!--导入MySQL的驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!--导入MyBatis的jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
1.1.5 导入sql语句
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`birthday` datetime default NULL COMMENT '生日',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES ('1', 'lucy', '123', '2018-12-12');
INSERT INTO `user` VALUES ('2', 'haohao', '123', '2019-12-12');
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ordertime` varchar(255) DEFAULT NULL,
`total` double DEFAULT NULL,
`uid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `uid` (`uid`),
CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `orders` VALUES ('1', '2018-12-12', '3000', '1');
INSERT INTO `orders` VALUES ('2', '2018-12-12', '4000', '1');
INSERT INTO `orders` VALUES ('3', '2018-12-12', '5000', '2');
1.1.6 创建Order和User实体
public class Order {
private int id;
private Date ordertime;
private double total;
//代表当前订单从属于哪一个客户
private int uid;
}
public class User {
private int id;
private String username;
private String password;
private Date birthday;
}
1.1.7 sqlMapConfig.xml
在resources目录下面新建mybatis的核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
核心配置文件
表示dtd的约束文件
约束文件的意思:所有的配置都需要放到configuration里面,这个里面需要设置各种属性,大概有十个属性,每个属性是有先后顺序,不能随意放置
所以他的名字叫约束文件
-->
<configuration>
<!-- 设置数据源的属性-->
<properties resource="jdbc.properties"></properties>
<!-- logImpl:表示日志的具体实现
STDOUT:标准输出
LOGGING:日志-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 设置别名-->
<typeAliases>
<!-- 在别名里面设置包名,mybatis会自动的在pojo里面去找他需要的javabean-->
<package name="com.atguigu.pojo"/>
</typeAliases>
<!--
数据源 事物管理器
-->
<!--配置环境变量
environments : 表示设置环境变量,但是环境变量可以设置多个
environment : 表示环境变量
id :表示唯一标示符,随便取名字,想叫什么都可以
default : 表示默认选中哪个环境变量, 注意: 必须跟下面的id保持一致
transactionManager : 表示事物管理器
type="JDBC" : 表示使用JDBC的事物管理器mybatis实际上是对JDBC的封装
MANAGED : 我们自己管理事物
dataSource :表示数据源
type="POOLED" : 表示数据库的连接池
数据源里面需要设置四个参数
驱动,url地址,用户名,密码
UNPOOLED :不适用数据库连接池
JNDI : 只可以跟EJB一起使用
-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--当前的版本 8.0以上,需要设置cj,如果在8.0以下,去掉cj-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
<!--设置URL地址
/// : 这个是主机和端口的缩写
localhost:3306
需要设置时区
北京:东八区,每15度一个区,一个区间隔一个小时
北回归线,广东,广西,云南
时区必须得写,其他的参数可写可不写
useUnicode=true :使用编码格式
characterEncoding=UTF-8 : 编码格式是UTF-8
& :链接符,转义字符 &
get请求:第一个参数 ? 第二个参数:&符号
serverTimezone=Asia/Shanghai ; 使用亚洲上海时区
不要使用UTC
allowPublicKeyRetrieval=true :使用秘钥,使用公钥,只有mysql8.0以上才有
-->
<property name="url" value="jdbc:mysql:///mybatis2?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"></property>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 表示使用配置文件的方式加载crud-->
<!-- <mapper resource="com/atguigu/dao/UserDao.xml"></mapper>-->
<!-- <mapper resource="com/atguigu/dao/OrderDao.xml"></mapper>-->
<package name="com.atguigu.dao"/>
</mappers>
</configuration>
1.1.8 创建OrderDao接口
package com.atguigu.dao;
import com.atguigu.pojo.Orders;
import java.util.List;
public interface OrdersDao {
/**
* 查询所有订单,并且把订单对应出来的所有用户给查询出来
* @return
*/
List<Orders> findAll();
}
1.1.9 配置OrderDao.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.atguigu.dao.OrderDao">
<!--查询所有-->
<select id="findAll" resultType="order">
select * from orders
</select>
</mapper>
1.1.10 测试结果
package com.atguigu;
import com.atguigu.dao.OrdersDao;
import com.atguigu.pojo.Orders;
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.InputStream;
import java.util.List;
public class MybatisTest {
// ctrl + alt + f :抽取成员变量
private SqlSession sqlSession;
private InputStream is;
private OrdersDao ordersDao;
/**
* 结束最后执行
*/
@After
public void after() throws Exception{
//提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
is.close();
}
/**
* 开始
*/
@Before
public void before() throws Exception{
//
// 1 需要找到核心配置文件
// ctrl + p : 表示查看参数
is = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2 构建会话工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 3 读取核心配置文件里面的io流
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
// 4 获取会话对象
sqlSession = sqlSessionFactory.openSession();
// 5 通过会话工厂,获取userdao对象
ordersDao = sqlSession.getMapper(OrdersDao.class);
}
@Test
public void testFindOrderAll(){
List<Orders> ordersList = ordersDao.findAll();
for (Orders orders : ordersList) {
System.out.println(orders);
}
}
}
使用resultMap,定义专门的resultMap用于映射一对一查询结果
修改Order类
在Order类中加入User类的对象作为Order类的一个属性
重新定义OrderDao.xml文件
resultMap常用标签
- resultMap,实现高级结果集映射的标签
- id :resultMap子标签,用于完成主键值的映射
- result :resultMap 子标签,用于完成普通列的映射
- association :resultMap 子标签,一个复杂的类型关联;许多结果将包成这种类型,用于处理一对一关系
- collection : resultMap 子标签,复杂类型的集合,用于处理一对多关系
1.1.11 第一种实现方式
<!-- 第一种实现方式-->
<resultMap id="orderMap" type="Orders">
<id column="id" property="user.id"></id>
<result column="username" property="user.username"></result>
<result column="password" property="user.password"></result>
<result column="birthday" property="user.birthday"></result>
</resultMap>
<select id="findAll" resultMap="orderMap">
select o.*,u.username,u.password,u.birthday from orders o, user u where o.uid = u.id;
</select>
1.1.12 第二种实现方式
<!-- 第二种实现方式-->
<!-- 使用resultMap 手动指定数据库字段和实体类属性之间的映射关系
type 用来指定最终哪个实体类来映射结果集
column 数据库的列
property 实体类的属性
javaType 属性的数据类型 可省略
jdbcType 数据库字段的数据类型 可省略-->
<resultMap id="orderMap" type="orders">
<id column="id" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
<association property="user" javaType="user">
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
</association>
</resultMap>
<!-- 通过订单查询用户 所以以订单表为主
之前不能关联 是因为在订单里面 没有用户的属性-->
<!-- <select id="findAll" resultType="Orders">-->
<select id="findAll" resultMap="orderMap">
select o.*,u.username,u.password,u.birthday from orders o, user u where o.uid = u.id;
</select>
1.1.13 测试结果
1.2 一对多查询
1.2.1 一对多查询的模型
用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单
1.2.2 一对多查询的语句
对应的sql语句:select * from user u , orders o where u.id=o.uid
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rn6uA1JM-1667820988079)(assets/image-20221107191124676.png)]
1.2.3 修改User实体
User类添加ordersList属性
1.2.4 创建UserDao接口
package com.atguigu.dao;
import com.atguigu.pojo.User;
import java.util.List;
public interface UserDao {
List<User> findAll();
}
1.2.5 配置UserDao.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.atguigu.dao.UserDao">
<!--
collection
部分定义了用户关联的账户信息。表示关联查询结果集
property="orderList":
关联查询的结果集存储在 User 对象的上哪个属性。
ofType="orders":
指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。-->
<resultMap id="userMap" type="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<collection property="ordersList" ofType="orders">
<result column="id" property="id"></result>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
</collection>
</resultMap>
<select id="findAll" resultMap="userMap">
select * from user u, orders o where u.id = o.uid;
</select>
</mapper>
1.2.6 测试结果
@Test
public void testFindUserAll(){
List<User> userList = userDao.findAll();
for (User user : userList) {
System.out.println(user);
}
}