java回顾:MyBatis参数、sql片段、动态sql、高级查询

目录

一、MyBatis参数

 SqlSessiong工具类

1、映射文件配置-入参

1.1 parameterType入参

1.2 单个入参,变量名任意定义:

1.3 多个入参,解决方案:

1.4 pojo类入参:

1.5 Map入参:

1.6 自增主键回填

2、参数值的获取

2.1 获取参数的方式

2.2 ${}取值的应用场景

3、结果集映射

3.1  简单结果映射resultType

3.2 resultType测例

3.3 结果映射resultMap

3.3 resultMap测例

3.4 resultMap标签映射流程 

4、SQL片段

4.1 引用当前文件中的SQL片段

二、动态sql(根据不同条件拼接SQL语句)

 1、OGNL表达式介绍

1.1 动态SQL中使用到的运算符: ognl表达式

2、动态SQL标签if、choose、where、set、foreach

2.1 if标签

2.2 if测例

2.3 choose标签:分支选择(多选一,遇到成立的条件即停止)

2.4 choose测例

2.5 where标签:拼接条件查询,去除多余and、or

2.6 where测例

2.7 set标签:update语句中,添加set关键字,会将动态sql最后多余的逗号去除

2.8 set测例

2.9 foreach标签:遍历集合或者数组,拼接成字符串用于sql中in关键字

2.10 foreach测例

2.11 特殊字符处理

三、高级查询

 1、一对一查询

1.1 一对一映射语法格式

1.2 一对一测例:

1.3 一对一查询映射规律

 2、一对多查询

1.1  一对多映射语法:

1.2 一对多测例 

1.3 一对多映射流程

1.4 一对多映小结

3、多对多查询

1.1 多对多映射

1.2 多对多测例

4、多对多查询扩展

5、ResultMap继承extend


一、MyBatis参数

 SqlSessiong工具类

public class SessionFactoryUtils {
    //声明一个工厂对象
    private static SqlSessionFactory factory;
    //在静态代码块中创建会话工厂
    static {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //得到输入流
        try(InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
            factory = builder.build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     静态方法得到会话工厂
     */
    public static SqlSessionFactory getSessionFactory() {
        return factory;
    }
    /**
     得到会话对象
     */
    public static SqlSession getSession() {
        return factory.openSession();//使用的是默认事务:手动提交
    }
}

1、映射文件配置-入参

1.1 parameterType入参

CRUD标签都有属性parameterType,底层的statement通过它指定接收的参数类型。入参数据有以下几种类型:HashMap,基本数据类型(包装类),实体类

在mybatis中入参的数据类型分为2大类:

  1. 基本数据类型:int,string,long,Date等;

  2. 复杂数据类型:类(pojo)和Map;

说明:如果传递参数是数组或者集合,底层都会封装到Map集合中。  

1.2 单个入参,变量名任意定义:

mapper.java
根据id查询用户信息,入参是单个参数:用户id
User queryById(Integer id); //接口方法传入一个参数
mapper.xml配置:

    
    

在xml中通过#{任意变量名}可接收到参数,若接口传入单个参数,可在xml中使用任意变量名接收

1.3 多个入参,解决方案:

mapper.java
多个入参,根据用户名和性别查询用户信息
User queryByNameAndSex(String name ,String sex);

错误演示:

    
    

报参数绑定异常!

需使用参数索引(arg0,arg1)、参数位置(param1,param2)、或在接口处明确指定传入参数名

方式1:使用参数索引获取:arg0,arg1 (了解即可) 


方式2:使用参数位置获取:param1,param2 (了解即可) 

掌握:命名参数获取,在接口处明确指定传入参数名称。

mapper.java接口

List queryByNameAndSex(@Param("name") String name,@Param("sex") String sex);

mapper.xml,变量名与接口中明确的@Param("name")参数名相同,接收参数时通过指定的名称获取参数值。

    
    

1.4 pojo类入参:

mapper.java接口

保存用户,pojo对象作为入参
int saveUser (User user);

mapper.xml,#{变量},变量名与User类中属性名对应


    
        insert into user values (null ,#{username},#{birthday},#{sex},#{address})
    

1.5 Map入参:

mapper.java接口

以map为参数插入用户信息
int saveUser2 (Map map);

        SqlSession sqlSession = SessionFactoryUtils.getSession();
        //获取接口代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map map = new HashMap<>();
        map.put("username","鞋垫老板");
        map.put("sex","男");
        map.put("address","鞋店");
        mapper.saveUser2(map);
        sqlSession.commit();
        sqlSession.close();

 mapper.xml


    
        insert into user values (null ,#{username},null,#{sex},#{address})
    

1.6 自增主键回填

 1)使用insert标签的子标签selectKey+last_insert_id()函数实现实现

   

    insert into user values(null,#{username},#{birthday},#{sex},#{address})                                
                        
            select last_insert_id()
        

 2)使用insert标签的属性useGeneratedKeys,keyProperty,keyColumn实现

说明:直接在insert标签中增加属性的方式,只适合于支持自动增长主键类型的数据库



    insert into user values(null,#{username},#{birthday},#{sex},#{address})

2、参数值的获取

2.1 获取参数的方式

在mybatis中获取传入参数值的方式有两种:#{} 和 ${}

#{}: 使用#{}的sql是进行预编译的,防止sql注入。

${}:参数与sql直接拼接有sql注入的风险。${id} 获取id值时,接口必须使用命名参数取值@param,若取单个值,也可使用${value}获取。

mapper.java接口
User findById2(@Param("id") Integer id);

mapper.xml

2.2 ${}取值的应用场景

如果需要设置到SQL中的不是查询的条件,只能使用${}拼接;

SELECT COUNT(*) FROM  ${tableName}

例:传入参数:没有指定参数名称

User selectUserById(Integer id);

获取参数通过${value}获取

3、结果集映射

        mybatis框架提供了resultType和resultMap来对结果集进行封装; 只要一个方法有返回值需要处理,那么 resultType和resultMap必须有一个;

3.1  简单结果映射resultType

        从sql语句中返回的期望类型的类的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。 可以使用 resultType 或 resultMap,但不能同时使用。

① 返回值是基本类型

        1)基本类型 int short double ...    别名: _基本类型名称

        2)包装类 类 String ArrayList ....   别名: 类名首字母小写

        3)自定义类 扫包取别名 类首字母小写(大写也可以)

② 返回值为一个pojo(User)对象时

        1)表中列明要与pojo中属性名称一致

        2)若表中列名与pojo中属性名称不一致,可使用as取别名使其一致即可

        3)如果满足驼峰映射,也可以开启驼峰映射设置

③返回值为一个List

        当返回值为List集合时,resultType需要设置成集合中存储的具体的pojo数据类型

 3.2 resultType测例

1)返回一条数据,封装到map中
接口:
Map findMapById(@Param("id") Integer id);
xml:

2)返回多条数据,封装到map中

获取所有用户,value为user对象:@MapKey("id"),指定key为id值

接口:
@MapKey("id")
Map findAllToMap();
xml:

3.3 结果映射resultMap

        正常开发中,数据库字段名称与Pojo类属性名称不一致时,一般通过驼峰映射或者AS关键字取别名可以搞定,但是对于复杂的orm映射,上述的2种方式就不能适用了。

        resultMap是mybatis中最重要最强大的元素,使用ResultMap可以解决ORM复杂映射问题:           1. POJO属性名和表结构字段名不一致的问题(字段名:user_name,属性名:name)             2. 完成高级查询,比如说,一对一、一对多、多对多

3.3 resultMap测例

        之前使用驼峰匹配,方便封装用户。现取消驼峰映射,使用ResultMap。

    
        
        
        
    

resultMap标签自定义结果集,自行设置结果集的封装方式。

id属性:resultMap标签的唯一标识,不能重复,一般是用来被引用的
type属性:结果集的封装类型
autoMapping属性:操作单表时,不配置默认为true,如果pojo对象中的属性名称和表中字段名称相同,则自动映射。

    
        
        
        
        
    
    
        SqlSession sqlSession = SessionFactoryUtils.getSession();
        //获取接口代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //调用方法根据id查询单个数据
        User user = mapper.findUserById(2);
        System.out.println("user = " + user);
        sqlSession.close();

注意:若xml中sql只查询数据库部分字段,需在pojo类加入无参构造,不然报索引超出边界异常

3.4 resultMap标签映射流程 

        提高了代码的复用性,结果集映射的;(将查询的结果映射到pojo类下)

java回顾:MyBatis参数、sql片段、动态sql、高级查询_第1张图片

4、SQL片段

4.1 引用当前文件中的SQL片段

sql标签可定义sql片段,在需使用该sql片段的地方,通过标签来使用 

定义sql片段

    id,user_name,birthday,sex,address


使用SQL片段,在SQL语句中通过``标签引入SQL片段

        若每个映射文件都编写一个相同的sql就比较麻烦,因此可将通用的sql片段都定义在一个专门存放sql片段的映射文件中,由其他映射文件引用即可。

        在src目录下新增commonSql.xml映射文件





    
    
        id,user_name,birthday,sex,address
    
    
        test1,test2,test3
    

 把该映射文件引入到mybatis的全局配置文件中(mybatis-config.xml):

    
        
        
    

引用sql片段

    

二、动态sql(根据不同条件拼接SQL语句)

 1、OGNL表达式介绍

        OGNL( Object Graph Navigation Language )对象图导航语言,这是一种强大的表达式语言,通过它可以非常方便的来操作对象属性。

1.1 动态SQL中使用到的运算符: ognl表达式

1.   e1 or e2 满足一个即可
2.   e1 and e2 都得满足
3.    e1 == e2 , e1 eq e2 判断是否相等
4.    e1 != e2 , e1 neq e2 不相等
5.    e1 lt e2:小于   lt表示less than 
6.    e1 lte e2:小于等于,其他gt(大于),gte(大于等于) gt 表示greater than
7.    e1 in e2 e2包含e1
8.    e1 not in e2  e2不包含e1
9.    e1 + e2,e1 * e2,e1/e2,e1 - e2,e1%e2
10.   !e,not e:非,求反
11.   e.method(args)调用对象方法
12.   e.property对象属性值  user.userName
13.   e1[ e2 ]按索引取值,List,数组和Map
14.   @class@method(args)调用类的静态方法
15.   @class@field调用类的静态字段值

2、动态SQL标签if、choose、where、set、foreach

 2.1 if标签

 
   满足条件sql加入拼接
 

说明:
 1)if标签:判断语句,用于进行逻辑判断的。如果判断条件为true,则执行if标签的文本内容
 2)test属性:用来编写表达式,支持ognl

2.2 if测例

查询男性用户,若输入用户名,按用户名模糊查询,若没输入用户名,查询所有男性用户

//接口
List findUsersByName(@Param("name") String name);
    
    
        
        
        
        
        

    

测试:

    @Test
    public void t8()  {
        SqlSession sqlSession = SessionFactoryUtils.getSession();
        //获取接口代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List usersByName = mapper.findUsersByName("%道%");
        System.out.println("usersByName = " + usersByName);
        sqlSession.commit();
        sqlSession.close();
    }

//usersByName = [
//    User{id=2, username='樱木花道', birthday=1992-11-12, sex='男', address='湘北高中一年'},         
//    User{id=14, username='仙道彰', birthday=1997-02-10, sex='男', address='陵南高中篮球队'}]

2.3 choose标签:分支选择(多选一,遇到成立的条件即停止)

choose标签:分支选择(多选一,遇到成立的条件即停止)
	when子标签:编写条件,不管有多少个when条件,一旦其中一个条件成立,后面的when条件都不执行
               test属性:编写ognl表达式
	otherwise子标签:当所有条件都不满足时,才会执行该条件。
    select  from user where sex = '男'
        
            
                and user_name like #{name}
            
            
                and address like #{address}
            
            
                and user_name = '樱木花道'
            
        

2.4 choose测例

编写一个查询方法,设置两个参数,一个是用户名,一个是住址
根据用户名或者住址查询所有男性用户:
	如果输入了用户名则按照用户名模糊查找,
	否则就按照住址查找,两个条件只能成立一个,
	如果都不输入就查找用户名为“樱木花道”的用户。
接口:
//根据用户名或者住址查询所有男性用户
List findUsersByNameOrAddress(@Param("name") String name ,@Param("address") String address);
    mapper.xml
    

测试:

    @Test
    public void t9()  {
        SqlSession sqlSession = SessionFactoryUtils.getSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        List usersByName = mapper.findUsersByNameOrAddress("%道%",null);
//        List usersByName = mapper.findUsersByNameOrAddress(null,"%湘北高中%");
        //所有条件都不满足,查询名字为‘樱木花道’
        List usersByName = mapper.findUsersByNameOrAddress(null,null);
        System.out.println("usersByName = " + usersByName);
        sqlSession.commit();
        sqlSession.close();
    }

2.5 where标签:拼接条件查询,去除多余and、or

格式:

    select  from user 
        
            
                user_name = #{name}
            
            
                and address = #{address}
            
        

2.6 where测例

若只输入用户名按照用户名查询;若只输入住址按住址查询;若两者都输入,则按照两个条件查询;若两者都未输入,全表查询;
//接口
List findUsersByNameAndAddress(@Param("name") String name ,@Param("address") String address);
mapper.xml:
    

 测试:

    //where标签:拼接条件查询,去除多余and、or
//    若只输入用户名按照用户名查询;若只输入住址按住址查询;若两者都输入,则按照两个条件查询;若两者都未输入,全表查询;
    @Test
    public void t10()  {
        SqlSession sqlSession = SessionFactoryUtils.getSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //无条件查全表
//        List usersByName = mapper.findUsersByNameAndAddress(null,null);
        //有名字查名字,有地址查地址,全有就全查
//        List usersByName = mapper.findUsersByNameAndAddress("%道%",null);
//        List usersByName = mapper.findUsersByNameAndAddress(null,"%湘北高中%");
        List usersByName = mapper.findUsersByNameAndAddress("%道%","%湘北高中%");
        System.out.println("usersByName = " + usersByName);
        sqlSession.commit();
        sqlSession.close();
    }

2.7 set标签:update语句中,添加set关键字,会将动态sql最后多余的逗号去除

格式:


    update t
        
        
        字段名1=值1,
        
        
        字段名2=值2,
        
        
    where 条件

2.8 set测例

修改用户信息,若参数user中的某个属性为null,则不修改。
//接口
int updateUserById(User user);

 set标签内循环,如条件不匹配自动省略”,“.

    
        update user
        
            
                user_name=#{username},
            
            
                birthday=#{birthday},
            
            
                sex=#{sex},
            
            
                address=#{address}
            
        
        where id = #{id}
    
    //set标签:去除被set标签包裹的多余的逗号','
    @Test
    public void t11()  {
        SqlSession sqlSession = SessionFactoryUtils.getSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(1,"赤木刚宪",null,null,null);
        int i = mapper.updateUserById(user);
        System.out.println("更新结果 = " + i);
        sqlSession.commit();
        sqlSession.close();
    }

2.9 foreach标签:遍历集合或者数组,拼接成字符串用于sql中in关键字

语法格式:

   #{元素}

说明:
collection属性:接收的集合名或者数组名(接口中定义的名字)
item属性:集合或者数组中的每个元素别名 ,用于#{}中
separator属性:标签分隔符 
open属性:以什么开始 
close属性:以什么结束

2.10 foreach测例

按照id值是1,2,3来查询(删除)用户数据 

//接口
List findByIds(@Param("ids") List ids);
    
    
//foreach标签:按照id值是1,2,3来查询(删除)用户数据,遍历集合或者数组,拼接成字符串用于sql中in关键字
    @Test
    public void t12()  {
        SqlSession sqlSession = SessionFactoryUtils.getSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List ids = new ArrayList<>();
        List list = Stream.of(1, 2,3).collect(Collectors.toList());
        List byIds = mapper.findByIds(list);
        System.out.println("查询结果 = " + byIds);
        sqlSession.commit();
        sqlSession.close();
    }

2.11 特殊字符处理

        在编写Mapper映射文件时,有时需用到一些诸如:>,<之类的特殊字符,不能直接书写在xml中,需对其处理。处理方式:使用转义字符代替特殊字符 

转义字符

sql符号

说明

<

<

小于

>

>

大于

&

&

和号

'

'

单引号

"

"

双引号

举例:批量将id小于3的用户查询出来,在映射文件中直接写<号,xml约束会报错!


三、高级查询

表与表的关系:

  • 一对一: ab两表的关系,由任意一张表维护(外键) 比如:b表维护ab的管理,那么在b表中创建一个字段aid
  • 一对多: ab两张表 比如:从a看是一个a对应b的多条数据,但是从b看是一个b只能对应一个a的数据
  • 多对多: ab两张表 比如:从a看是一个a对应b的多条数据,同时从b看是一个b对应a表的多条数据

数据准备 

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for tb_item
-- ----------------------------
DROP TABLE IF EXISTS `tb_item`;
CREATE TABLE `tb_item` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `item_name` varchar(32) NOT NULL COMMENT '商品名称',
  `item_price` float(6,1) NOT NULL COMMENT '商品价格',
  `item_detail` text COMMENT '商品描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_item
-- ----------------------------
INSERT INTO `tb_item` VALUES ('1', 'iPhone 6', '5288.0', '苹果公司新发布的手机产品。');
INSERT INTO `tb_item` VALUES ('2', 'iPhone 6 plus', '6288.0', '苹果公司发布的新大屏手机。');

-- ----------------------------
-- Table structure for tb_order
-- ----------------------------
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL,
  `order_number` varchar(20) NOT NULL COMMENT '订单号',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_orders_1` FOREIGN KEY (`user_id`) REFERENCES `tb_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_order
-- ----------------------------
INSERT INTO `tb_order` VALUES ('1', '1', '20140921001');
INSERT INTO `tb_order` VALUES ('2', '2', '20140921002');
INSERT INTO `tb_order` VALUES ('3', '1', '20140921003');

-- ----------------------------
-- Table structure for tb_orderdetail
-- ----------------------------
DROP TABLE IF EXISTS `tb_orderdetail`;
CREATE TABLE `tb_orderdetail` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(32) DEFAULT NULL COMMENT '订单号',
  `item_id` int(32) DEFAULT NULL COMMENT '商品id',
  `total_price` double(20,0) DEFAULT NULL COMMENT '商品总价',
  `status` int(11) DEFAULT NULL COMMENT '状态',
  PRIMARY KEY (`id`),
  KEY `FK_orderdetail_1` (`order_id`),
  KEY `FK_orderdetail_2` (`item_id`),
  CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`order_id`) REFERENCES `tb_order` (`id`),
  CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`item_id`) REFERENCES `tb_item` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_orderdetail
-- ----------------------------
INSERT INTO `tb_orderdetail` VALUES ('1', '1', '1', '5288', '1');
INSERT INTO `tb_orderdetail` VALUES ('2', '1', '2', '6288', '1');
INSERT INTO `tb_orderdetail` VALUES ('3', '2', '2', '6288', '1');
INSERT INTO `tb_orderdetail` VALUES ('4', '3', '1', '5288', '1');

-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(100) DEFAULT NULL COMMENT '用户名',
  `password` varchar(100) DEFAULT NULL COMMENT '密码',
  `name` varchar(100) DEFAULT NULL COMMENT '姓名',
  `age` int(10) DEFAULT NULL COMMENT '年龄',
  `sex` int(11) DEFAULT NULL COMMENT '0-女 1-男',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`user_name`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES ('1', 'zhangsan', '123456', '樱木花道', '30', '1');
INSERT INTO `tb_user` VALUES ('2', 'lisi', '123456', '赤木刚宪', '21', '0');
INSERT INTO `tb_user` VALUES ('3', 'wangwu', '123456', '流川枫', '22', '1');
INSERT INTO `tb_user` VALUES ('4', 'zhangwei', '123456', '宫城良田', '20', '1');
INSERT INTO `tb_user` VALUES ('5', 'lina', '123456', '三井寿', '28', '0');

 order订单类:

public class Order {

    private Integer id;
    private String orderNumber;
    //实现一对一映射 加入类型为User的order属性
    private User2 orderUser;

    getter、setter、toString...
}

user用户类:

public class User2 implements Serializable{

    private Long id;
    // 用户名
    private String userName;
    // 密码
    private String password;
    // 姓名
    private String name;
    // 年龄
    private Integer age;
    //0-女 1-男
    private Integer sex;

    getter、setter、toString...
}

 item商品类:

public class Item {

    private Integer id;
    private String itemName;
    private Float itemPrice;
    private String itemDetail;

    getter、setter、toString...
}

 orderdetail 订单明细类:

public class Orderdetail {
    
    private Integer id;
    private Double totalPrice;
    private Integer status;
    
    getter、setter、toString...
}

 1、一对一查询

 1.1 一对一映射语法格式


    
    ......
    
    
    
    

java回顾:MyBatis参数、sql片段、动态sql、高级查询_第2张图片

若使用as取别名,则column="别名"。 

    
        
        
        
        
        
            
            
            
        
    

1.2 一对一测例:

通过订单编号20140921003查询出订单信息,并查询出下单人信息

    //高级查询  一对一 通过订单编号20140921003查询出订单信息,并查询出下单人信息
    Order findUserByOrderNum(@Param("orderNumber") String orderNumber);

若使用as取别名,则column="别名"。 


    
        
        
        
        
        
        
            
            
            
        
    

    
    
//通过订单编号20140921003查询出订单信息(以订单为返回)
//高级查询  一对一 通过订单编号20140921003查询出订单信息,并查询出下单人信息
    @Test
    public void t2() {
        final SqlSession session = SessionFactoryUtils.getSession();
        final UserMapper mapper = session.getMapper(UserMapper.class);
        final Order userByOrderNum = mapper.findUserByOrderNum("20140921003");
        System.out.println("userByOrderNum = " + userByOrderNum);
        session.close();
    }

 1.3 一对一查询映射规律

java回顾:MyBatis参数、sql片段、动态sql、高级查询_第3张图片

 实现步骤:

1) 维护pojo对象之间一对一的关系:

        Order 包含属性:User类型的变量

2) 配置一对一的映射关系:

   
             
             
             
                               
                         
               
        

 2、一对多查询

1.1  一对多映射语法:

若使用as取别名,则column="别名"。

    
    
        
        
        
        
        
            
            
            
            
        
    

    
    

1.2 一对多测例 

//查询id为1的用户及其订单信息(以用户为返回)
//高级查询  一对一 通过订单编号20140921003查询出订单信息,并查询出下单人信息
    User2 findUserAndOrderById(@Param("userId") Long userId);
public class User implements Serializable{
    private List orders;
    private Long id;
    private String userName; // 用户名
    private String password; // 密码
    private String name; // 姓名
    private Integer age; // 年龄
    private Integer sex; //0-女 1-男
// getter  and setter and toString
}
//高级查询 一对多 查询id为1的用户及其订单信息(以用户为返回) 一个用户可以有多个订单,一个订单只能属于一个用户,用户(1)-订单(n)
    @Test
    public void t3() {
        final SqlSession session = SessionFactoryUtils.getSession();
        final UserMapper mapper = session.getMapper(UserMapper.class);
        final User2 userAndOrderById = mapper.findUserAndOrderById(1L);
        System.out.println("userAndOrderById = " + userAndOrderById);
        session.close();
    }
/*User2{userOrder=[
            Order{id=1, orderNumber='20140921001', orderUser=null},
            Order{id=3, orderNumber='20140921003', orderUser=null}],
            id=1, userName='zhangsan', password='123456', name='樱木花道', age=30, sex=1}*/

1.3 一对多映射流程

1.4 一对多映小结

在一对多的场景中,一般主表中通过创建一个集合属性来包含从表的数据

user类包含List orders);

3、多对多查询

1.1 多对多映射

多对多查询本质是一对多和一对一查询的组合,核心标签用法如下:


    
    
    
        
        
        
        
            
            
        
    

1.2 多对多测例

查询订单号为20140921001的订单,包含订单详情信息以及订单中的商品信息
select orders.id order_id, orders.order_number,
	detail.id detail_id, detail.status, detail.total_price,
	item.id, item.item_name, item.item_price, item.item_detail
from tb_order orders, tb_orderdetail detail, tb_item item
where orders.id = detail.order_id
and detail.item_id = item.id
and orders.order_number = '20140921001';
//‘订单’类关联‘订单详情’属性
public class Order {
    private Integer id;
    private String orderNumber;
    private User user;
    private List orderdetailList;
    ...
}

// 每一条订单详情记录中都包含了一条商品信息
//‘订单详情’类关联‘商品’属性
public class Orderdetail {
    private Integer id;
    private Double totalPrice;
    private Integer status;
    private Item item;
    ......
}
    
    
        
        
        
        
        
            
            
            
            
            
            
            
                
                
                
                
                
                
            
        
    

    
    
//高级查询  多对多 返回订单 查询订单号为20140921001的订单,包含订单详情信息以及订单中的商品信息
Order findDetailAndItem(@Param("orderNumber")String orderNumber);
//高级查询 多对多 返回订单 查询订单号为20140921001的订单,包含订单详情信息以及订单中的商品信息
    @Test
    public void t4() {
        final SqlSession session = SessionFactoryUtils.getSession();
        final UserMapper mapper = session.getMapper(UserMapper.class);
        final Order detailAndItem = mapper.findDetailAndItem("20140921001");
        System.out.println("多对多 = " + detailAndItem);
        session.close();
    }

4、多对多查询扩展

查询订单号为20140921001的订单信息、订单所属用户信息、订单中的详细商品信息

SELECT  
    tb_user.id as user_id,  tb_user.age,  tb_user.`password`,  tb_user.sex,        
    tb_user.user_name,  tb_user.`name`, tb_order.id AS order_id,  tb_order.order_number,
    tb_orderdetail.id AS detail_id, tb_orderdetail.total_price,  tb_orderdetail.`status`,
    tb_item.*
FROM
    tb_order, tb_orderdetail, tb_item, tb_user
WHERE
    tb_order.id = tb_orderdetail.order_id
AND tb_orderdetail.item_id = tb_item.id
AND tb_order.user_id=tb_user.id
AND tb_order.order_number = ? 
//根据订单编号查询订单信息,用户信息和订单详情信息以及关联的商品信息
Order findByOrderNumber3(@Param("orderNumber") String orderNumber);


    
    
    
        
        
    

    
        
        
        
        
            
            
        
    


5、ResultMap继承extend

若两个ResultMap结果集有重叠的部分,可以通过extend属性继承简化;

将上述扩展通过extends继承后简化映射文件配置:


    
        
        
    

你可能感兴趣的:(java回顾,mybatis,java,sql)