目录
- 复习昨天的Maven web工程的搭建
-
- 目录结构
- 学习目标
- ResultMap
- 关联查询
-
- 一对一(1)
- 一对一(2)
- 联查询-一对多
复习昨天的Maven web工程的搭建
目录结构
- –jave
- ----util
- ------Mybatis.java
- ----bean
- ------User.java(实体类爱谁谁谁)
- ----dao
- ------UserDao.java(持久层,需要创建映射文件)
- –resources
- ----log4j.properties
- ----SqlMapConfig.xml
- ----UserDao.xml
- –test
- ----pack01
- ------Test01
- pom.xml
src\main\resources\SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--dtd是对xml配置标签与属性的约束-->
<configuration><!-- environments环境 开发环境,生产环境--><environments default="development"><environment id="development"><!-- 使用jdbc的事务管理 --><transactionManager type="JDBC"/><!-- dataSource Mybatis自带数据源连接池--><dataSource type="POOLED"><!-- 四大信息 --><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis02?characterEncoding=utf-8"/><property name="username" value="root"/><property name="password" value=""/></dataSource></environment></environments><!-- 配置多个映射文件-->
<!-- <mappers>-->
<!-- <!– <mapper resource="UserMapper.xml"/>-->
<!-- <mapper resource="UserDao.xml"/>–>-->
<!-- </mappers>--></configuration>
src\main\java\com\vission\util\MySessionUtils.java
public class MySessionUtils {
private static SqlSessionFactory sessionFactory;//static 静态代码,在类加载的时候执行一次,且只执行一次static{
// 》1 创建SqlSessionFactoryBuilder对象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 》2 创建SqlSessionFactory对象InputStream inputStream = MySessionUtils.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");sessionFactory = sqlSessionFactoryBuilder.build(inputStream);//加载核心配置文件 参1 输入流
// 》3 加载SqlMapConfig.xml配置文件}public static SqlSession getSession() {
// 》4 创建SqlSession对象SqlSession sqlSession = sessionFactory.openSession();return sqlSession;}
}
- 由于我们昨天已经会创建工具类MySessionUtils.java了所以我们在test类里面直接调用
SqlSeesion session = MySessionUtils.getSeesion();
src\test\java\com\vission\pack01\test01.java
package com.vission.pack01;
import com.vission.util.MySessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;public class test01{
@Testpublic void test01(){
SqlSession session = new MySessionUtils().getSession();System.out.println(session);session.commit();session.close();}
}
pom.xml
<!-- junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><!-- MySql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.32</version></dependency><!-- Mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version></dependency><!--日志包--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.25</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>
src\main\resources\log4j.properties
当然还有日志文件不能丢了
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
SqlMapConfig.xml ----> log4j.properties---->MySeesionUtils.java ---->Test01.java---->pom.xml
这几个文件都弄完了我们就来测试一下吧
看看是否能连上数据库
- 就很nice就很棒,眼前一片绿光告诉我ok了
使用老师给的数据
create database mybatis02;
use mybatis02;create database day13 default charset='UTF8';use day13;create table user (id int(11) primary key auto_increment,username varchar(32) not null comment '用户名称',birthday date default null comment '生日',sex char(1) default null comment '性别',address varchar(256) default null comment '地址');insert into `user` values (null, '王五', '2015-05-10', '2', null);
insert into `user` values (null, '张三', '2014-07-10', '1', '北京市');
insert into `user` values (null, '张小明', '2018-11-11', '1', '郑州');
insert into `user` values (null, '陈小明', '2019-07-20', '1', '广州');
insert into `user` values (null, '张三丰', '2011-04-11', '1', '西安');
insert into `user` values (null, '陈小明', '2019-09-10', '2', '杭州');
insert into `user` values (null, '王五', '2014-07-07', null, null);#创建订单表
create table `order`(id int primary key auto_increment,user_id int not null ,number varchar(50) not null,createtime datetime not null,note varchar(100) default null,constraint FK_order_id foreign key (user_id) references user(id)
);insert into `order` values ('3', '1', '1000010', '2018-02-04 13:22:35', '备注3');
insert into `order` values ('4', '1', '1000011', '2017-02-03 13:22:41', null);
insert into `order` values ('5', '5', '1000012', '2019-02-12 16:13:23', null);
insert into `order` values ('6', '6', '1000012', '2025-02-12 16:13:23', null);
insert into `order` values ('7', '7', '1000012', '2020-02-12 16:13:23', null);
根据数据库创建实体类Order
src\main\java\com\vission\bean\Order.java
package com.vission.bean;
import java.sql.Date;public class Order {
// 订单idprivate int id;// 用户idprivate int user_Id;// 订单号private String number;// 订单创建时间private Date createtime;// 备注private String note;
.
.
.//get set tostring}
定义OrderDao接口
src\main\java\com\vission\dao\OrderDao.java
public interface OrderDao {
//select * from `order`;public List<Order> findAll();
}
映射文件实现OrderDao功能代码OrderDao.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.vission.dao.OrderDao"><select id="findAll" resultType="com.vission.bean.Order">select * from order_01;</select>
</mapper>
核心文件SqlMapConfig.xml
src\main\resources\SqlMapConfig.xml
<!-- 配置多个映射文件--><mappers><mapper resource="OrderDao.xml"/></mappers>
编写测试类
public class test02 {
@Testpublic void test01(){
SqlSession session = new MySessionUtils().getSession();OrderDao orderDao = session.getMapper(OrderDao.class);List<Order> list = orderDao.findAll();System.out.println(list);
// System.out.println(session);session.commit();session.close();}
}
测试成功
然后就开始我们今天的学习能容了
学习目标
-
ResultMap标签(重要)
查询数据封装的原理
字段名和成员名不一致
ResultMap标签 -
动态sql(重要)
动态sql-if标签
动态sql-foreach标签 -
关联查询(重要)
关联查询-一对一
关联查询-一对多
关联查询-综合案例
-
字段名和成员名不一致 为什么id属性能被Mybatis赋值?
底层使用id生成setId,使用反射调用setId方法,setId(10) 方法内完成赋值 id = 10 -
为什么user_id属性能被Mybatis赋值?
底层使用user_id生成setUser_id
使用反射调用setUser_id方法,类中只有setUserId -
所以为什么强调表与类的对应关系?
字段名和成员名要一致
ResultMap
(1)ResultMap有什么用?
建立查询字段与实体类成员变量的映射关系
即:查询字段是user_id但是Mybatis去赋值userId
字段名与变量名不一致,可以赋值
实现一对多,多对多的查询
(2)ResultMap标签映射关系,resultMap使用
在不改表,也不改类的基础上,完成查询数据对变量的赋值。
在Order.xml里加入一个< resultMap >标签
<resultMap id="ResultMap标识" type="指定你要映射哪一个JavaBean"></resultMap>
<!--id:ResultMap标识,标签语句中 resultMap的值必须和该id一致type:指定你要映射哪一个JavaBean如果字段名和成员名一样,则可以不用指定映射关系--><resultMap id="resultMap1" type="com.vission.bean.Order"><!--在这里要指定数据库表字段和JavaBean成员变量之前的映射关系--><!--先指定主键字段和成员之间的映射关系--><id column="id" property="id"></id><!--先指定非主键字段和成员之间的映射关系column:字段名property:成员变量名--><result column="user_id" property="userId"></result><result column="number" property="number"></result><result column="createtime" property="createtime"></result><result column="note" property="note"></result></resultMap><select id="queryAllOrders" resultMap="resultMap1">SELECT id,user_id,number,createtime,note FROM orderx</select>
这里没有resultMap的处理映射,直接将从数据库中处理的数据返回给了bean实例对象
实例对象Order里一样的字段都可以通过set()方法设置值,不一样的像对象中userId无法获取值
没加映射前
加了映射后
关联查询
- 关联查询
- 项目不可能只有一个表,一般是多表
- 多表关系为,一对一,一对多,多对多
- 查询的数据来自多个表,要使用多表查询
笛卡尔集,显示内连接inner join,左外连接left outer join,右外连接right outer join,子查询select嵌套select
查询的结果要封装成javaBean对象 ,在Mybatis中重点掌握resultType与resultMap
一对一(1)
- 关联查询的中的一对一是指,站在订单的角度看,一个订单有一个用户跟它对应
- 数据来自两个表,使用连接查询,需要输出所有订单,使用左外连接
- 查询结果可以有两种方式封装数据
- resultType 指定一个自定义javaBean类(通常要再编写一个新的javaBean类)
- resultMap 指定映射关系(不用编写新的javaBean类 推荐使用)
src\main\java\com\vission\bean\OrderUser.java
public class OrderUser {
//订单的属性private int oid;private Integer user_id;private String number;private Date createtime;private String note;//用户的属性private int uid;private String username;private Date birthday;private String sex;private String address;
}
src\main\java\com\vission\dao\OrderUserDao.java
public interface OrderUserDao {
/*select o.id as oid,o.user_id ,o.number,o.createtime,o.note,u.id as uid,u.username,u.birthday,u.sex,u.addressfrom `order` o left join `user` uon o.user_id=u.id;*/List<OrderUser> findAllOrderUser();
}
src\main\resources\OrderUserDao.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.vission.dao.OrderUserDao">
<!-- <select id="findAll" resultType="com.vission.bean.OrderUser">-->
<!-- select * from order_01;-->
<!-- </select>--><!--<resultMap id="OrderUserMap" type="com.vission.bean.OrderUser">-->
<!-- <result column="user_id" property="userId"></result>-->
<!--</resultMap>--><select id="findAllOrderUser" resultType="com.vission.bean.OrderUser">select o.id as oid,o.user_id ,o.number,o.createtime,o.note,u.id as uid,u.username,u.birthday,u.sex,u.addressfrom order_01 o left join user uon o.user_id=u.id;</select>
</mapper>
src\main\resources\SqlMapConfig.xml
<mappers><mapper resource="OrderDao.xml"/><mapper resource="OrderUserDao.xml"/></mappers>
一对一(2)
这里是第二种方法,假设我们没有创建OrderUser类,那我也要同时查询Order,User的信息要怎么做呢?既然如此首先我们得有两个Bean类分别是Order.java、User.java,我们将User类嵌套在Order类里面,这样只要我们用一段sql语句左联表查询就可以同时查询出Order和User的信息,至于怎么处理这些信息,我们全部丢到resultMap里去处理,将获取的Order用正常的映射
<result column="数据库的字段名" property="Bean内的字段名"></result>
Sql的信息肯定是不能封装到Order里面,User的信息我们用resultMap的子标签association来处理
<association property="对象名,这里我们自然填的就是user" javaType="该对象完整的地址" autoMapping="true" ><id column="id" property="uid"></id></association>
这里补充一点:resultMap的子标签id与result,一个是唯一标识符主键,一个是普通属性值
Order类
public class Order {
// 订单idprivate int id;// 用户idprivate Integer userId;// 订单号private String number;// 订单创建时间private Date createtime;// 备注private String note;//增加User成员变量来接收一条记录的用户的查询字段。private User user;}
然后我们在OrderDao.xml里的resultMap加入
- 分析下属性
- association 标签用于成员变量的类型为自定义实体类型
- 添加属性:autoMapping=“true”,自动映射
这个一般都是打开的
User类
src\main\java\com\vission\bean\User.java
public class User {
private int uid;private String username;private Date birthday;private String sex;private String address;
测试类
src\test\java\com\vission\pack01\test03.java
@Testpublic void test01(){
//ResultMap=>原来的Order类SqlSession session = MySessionUtils.getSession();//update insert delete findOrderDao orderDao = session.getMapper(OrderDao.class);List<Order> list=orderDao.findAllOrder2();System.out.println(list);//关闭资源session.commit();session.close();}
OrderDao
src\main\java\com\vission\dao\OrderDao.java
public interface OrderDao {
//select * from `order`;public List<Order> findAll();List<Order> findAllOrderUser();List<Order> findAllOrder2();
}
OrderDao.xml
src\main\resources\OrderDao.xml
<resultMap id="findAllOrder2Map" type="com.vission.bean.Order" autoMapping="true"><!--先指定Order类属性和字段之间的映射关系--><id column="id" property="id"></id><result column="user_Id" property="userId"></result><!--先指定Order类中User类属性和字段之间的映射关系property:表示Order类中User类对象的名字javaType:表示Order类中包含的User类的全路径名autoMapping:表示如果字段名和属性名一致,则自动映射class Order{User user;}--><association property="user" javaType="com.vission.bean.User" autoMapping="true" ><id column="id" property="uid"></id></association></resultMap><select id="findAllOrder2" resultMap="findAllOrder2Map">select o.id as id,o.user_id,o.number,o.createtime,o.note,
-- u.id as uid,u.id,u.username,u.birthday,u.sex,u.addressfrom order_01 o left join user uon o.user_id=u.id;</select>
运行测试类
成功将User对象嵌套入Order,算是给OrderUser对象解耦了,个人认为更方便维护
联查询-一对多
- 关联查询的中的一对多是指,站在用户的角度看,一个用户会存在多个订单跟他对应。
- 数据来自两个表,使用连接查询,需要输出每一个用户有多少个订单
- 查询结果使用collection标签 映射List<元素>
编写测试类
src\test\java\com\vission\pack01\test04.java
public class test04 {
@Testpublic void test01(){
SqlSession session = new MySessionUtils().getSession();UserDao userDao = session.getMapper(UserDao.class);List<User> list = userDao.findAllUser(1);System.out.println(list);session.commit();session.close();}
}
User类
src\main\java\com\vission\bean\User.java
public class User {
private int uid;private String username;private Date birthday;private String sex;private String address;private List<Order> orderList;...}
UserDao接口
src\main\java\com\vission\dao\UserDao.java
public interface UserDao {
List<User> findAllUser(int id);
}
UserDao.xml功能代码
src\main\resources\UserDao.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.vission.dao.UserDao"><resultMap id="findAllUserMap" type="com.vission.bean.User" autoMapping="true">
<!-- <id column="id" property="uid"></id>--><collection property="orderList" ofType="com.vission.bean.Order" autoMapping="true"><id column="oid" property="id"></id><result column="user_id" property="userId"></result></collection></resultMap><select id="findAllUser" resultMap="findAllUserMap">selectu.id as uid,u.username,u.birthday,u.sex,u.address,o.id as oid,o.user_id,o.number,o.createtime,o.notefrom user u left join order_01 oon o.user_id=u.id where u.id = #{id};</select>
</mapper>
SqlMapConfig.xml文件
src\main\resources\SqlMapConfig.xml
<mappers><mapper resource="OrderDao.xml"/><mapper resource="OrderUserDao.xml"/><mapper resource="UserDao.xml"/></mappers>
运行测试类
[User{uid=1, username='王五', birthday=2015-05-10, sex='2', address='null', orderList=[Order{id=3, userId=1, number='1000010', createtime=2018-02-04, note='备注3', user=null}]},
User{uid=1, username='王五', birthday=2015-05-10, sex='2', address='null', orderList=[Order{id=4, userId=1, number='1000011', createtime=2017-02-03, note='null', user=null}]}]