当前位置: 代码迷 >> 综合 >> Day15 JavaWeb【Mybatis二】
  详细解决方案

Day15 JavaWeb【Mybatis二】

热度:39   发布时间:2024-02-22 23:35:37.0

目录

  • 复习昨天的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>-->
<!-- &lt;!&ndash; <mapper resource="UserMapper.xml"/>-->
<!-- <mapper resource="UserDao.xml"/>&ndash;&gt;-->
<!-- </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无法获取值
在这里插入图片描述

没加映射前
在这里插入图片描述
加了映射后
在这里插入图片描述

关联查询

  • 关联查询
  1. 项目不可能只有一个表,一般是多表
  2. 多表关系为,一对一,一对多,多对多
  3. 查询的数据来自多个表,要使用多表查询
    笛卡尔集,显示内连接inner join,左外连接left outer join,右外连接right outer join,子查询select嵌套select
    查询的结果要封装成javaBean对象 ,在Mybatis中重点掌握resultType与resultMap
    在这里插入图片描述

一对一(1)

  1. 关联查询的中的一对一是指,站在订单的角度看,一个订单有一个用户跟它对应
  2. 数据来自两个表,使用连接查询,需要输出所有订单,使用左外连接
  3. 查询结果可以有两种方式封装数据
  • 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.javaUser.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加入

  1. 分析下属性
  2. association 标签用于成员变量类型为自定义实体类型
  3. 添加属性: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对象解耦了,个人认为更方便维护
在这里插入图片描述

联查询-一对多

  1. 关联查询的中的一对多是指,站在用户的角度看,一个用户会存在多个订单跟他对应。
  2. 数据来自两个表,使用连接查询,需要输出每一个用户有多少个订单
  3. 查询结果使用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}]}]
  相关解决方案