持久层框架MyBatis 多表查询一对多、高级搜索、动态SQL语句

持久层框架MyBatis 多表查询 一对多

往期内容:持久层框架MyBatis 多表查询 一对一

需求

商品分类表
在这里插入图片描述

商品详情表
在这里插入图片描述

SELECT category.category_id,category.category_name,item_name
FROM category,item
WHERE category.category_id=1 AND item.category_id=category.category_id
在这里插入图片描述

1.表的关系

在这里插入图片描述

2.分析

在这里插入图片描述

3.实现步骤

1.在mybatis04项目pojo包中创建Item、category实体类
2.在mapper包中创建CategoryMapper接口{Category select(Integer categoryld)}
3.在mapper包中创建CategoryMapper.xml


result
select
4.在controller包中创建CategoryController
@autowired
CategoryMapper categoryMapper

@requestmMapping(/select)
Category select (){
return categoryMapper.select()
}



1.打开eclipse,找到mybatis04中的pojo包

在这里插入图片描述

2.创建Item类、Category类

在这里插入图片描述

package com.tedu.DbDemo.pojo;

//对应Item表
public class Item {
    
    
   String itemName;//对应item_name列
   //set()、get()

public String getItemName() {
    
    
	return itemName;
}

public void setItemName(String itemName) {
    
    
	this.itemName = itemName;
}
}
package com.tedu.DbDemo.pojo;

import java.util.List;

//对应Category表
public class Category {
    
    
     Integer categoryId;//对应Category_id列
     String categoryName;//对应Category_name列
     //一个分类下有多个商品
     List <Item> itemList;//体现出一对多关系
     
   //set、get
	public Integer getCategoryId() {
    
    
		return categoryId;
	}
	public void setCategoryId(Integer categoryId) {
    
    
		this.categoryId = categoryId;
	}
	public String getCategoryName() {
    
    
		return categoryName;
	}
	public void setCategoryName(String categoryName) {
    
    
		this.categoryName = categoryName;
	}
	public List<Item> getItemList() {
    
    
		return itemList;
	}
	public void setItemList(List<Item> itemList) {
    
    
		this.itemList = itemList;
	}   
}

3.在mapper包中创建接口CategoryMapper类、CategoryMapper.xml

在这里插入图片描述

package com.tedu.DbDemo.mapper;

import com.tedu.DbDemo.pojo.Category;

public interface CategoryMapper {
    
    
    //查询员工分类和分类下的所有商品
	public Category selectById(Integer categoryId);
}
<?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">
<!-- namespace="接口的包名.接口名" -->
<mapper namespace="com.tedu.DbDemo.mapper.CategoryMapper">
<!-- type=com.tedu.DbDemo.pojo.Category -->
<resultMap type="com.tedu.DbDemo.pojo.Category" id="map1">
<!-- 顺序是result、colleciton -->
<result column="category_id" property="categoryId"/>
<result column="category_name" property="categoryname"/>
<!-- 结果集中有商品信息,分类和商品是一对多 -->
<!-- 一对多用collection 一对一用assiocation -->
<!-- Category{List<Item> itemList}  -->
<collection property="itemList" ofType="com.tedu.DbDemo.pojo.Item">
<result column="item_name" property="itemName"/>
</collection>
</resultMap>
<!-- resultType=Category
     resultMap=map
     parameterType=Integer
     parameterMap
-->
<select id="selectById" resultMap="map1" parameterType="Integer">
SELECT category.category_id,category_name,item_name
FROM category,item
WHERE category.category_id=#{categortId}
AND item.category_id=category.category_id
</select>
</mapper>

select元素有很多属性(这里说用的比较多的):
id:命名空间唯一标识,可以被用来引用这条语句
<font face=“宋体” color=#FF0000size=5> parameterType:将会传入这条语句的参数类的完全限定名或者别名
resultType:从这条语句要返回的期望类型的类的完全限定名或别名(这里注意下集合类型,应该是集合可以包含的类型,不能是集合本身),重要:使用resultType或resultMap,但不能同时使用。
resultMap:命名引用外部的resultMap,其名称要和外部的resultMap元素的ID名称一致,用于映射其结果到实体类指定对象中。

4.在controller包中创建CategoryController类

在这里插入图片描述

package com.tedu.DbDemo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tedu.DbDemo.mapper.CategoryMapper;
import com.tedu.DbDemo.pojo.Category;

@RestController
public class CategoryController {
    
    
	//@mapperScan(mapper) mybatis框架会自动为mapper包下的
	//接口创建代理类$proxy51,为代理类创建代理对象
	//放在spring的ioc 容器中
	//autowired得到代理对象
	//执行selectById(),mybatis框架会从xml中找到select语句
	//执行sql得到的是结果集,把每一行转成Category对象
	//把对象放在list中,结果集中就一行数据,返回一个对象
	//由jackson框架把数据转成json
	@Autowired
	CategoryMapper categoryMapper;
	
	@RequestMapping("/category")
	public Category selectById() {
    
    
		Category category=categoryMapper.selectById(1);
		return category;
	}
}

Run As执行:
http://localhost:8080/category
在这里插入图片描述



4.参数占位符

mybatis本质就是拼接SQL语句。

#{name}

使用的jdbc的ParpareStatment。
#{} 很赞,防止SQL注入;如果参数是一个字符串类型。
chen 拼接SQL语句时会根据类型,自动加相关符号。例如字符串类型’chen’。

${orderby}

${} 原样输出,很危险,有SQL注入风险。
测试:
在这里插入图片描述

查看控制台输出的SQL语句:
==> Preparing: select category.category_id,category_name,item_name from category,item where category.category_id=1 and item.category_id=category.category_id
> Parameters:
<
Total: 2


工作中必须用#{},因为他安全,防止SQL注入!



5.复杂搜索案例

Baidu高级搜索

在这里插入图片描述

github.com/search/advanced

在这里插入图片描述

6.动态SQL语句

在这里插入图片描述

在这里插入图片描述

6.1 在mapper包下创建ItemMapper{listselect(Item)},pojo包下的Item添加categoryld
6.2 在mapper包下面创建ItemMapper.xml

doctype
mapper namespace
不用写resultMap

select
select category_id as categoryld,item_name as itemName
where
<if test="categoryId!=null">
category_id=#{
    
    categoryId} 
</if>
6.3打开Item类,进行修改
package com.tedu.DbDemo.pojo;
//对应Item表
public class Item {
    
    
	String itemName;//对应item_name列
	Integer categoryId;
	//set(),get()

	public String getItemName() {
    
    
		return itemName;
	}
	public void setItemName(String itemName) {
    
    
		this.itemName = itemName;
	}
	public Integer getCategoryId() {
    
    
		return categoryId;
	}
	public void setCategoryId(Integer categoryId) {
    
    
		this.categoryId = categoryId;
	}
}

7.在mapper包中创建接口 ItemMapper类、ItemMapper.xml

在这里插入图片描述
创建ItemMapper.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">
<!-- namespace="接口的包名.接口名" -->
<mapper namespace="com.tedu.DbDemo.mapper.ItemMapper">
<!-- List<Item> select1() -->
<!-- 如果方法返回的是集合,resultType的值是集合中数据的类型,resultType指定的是结果集中的每一行转成哪个类 -->
<select id="select1" parameterType="com.tedu.DbDemo.pojo.Item" 
                     resultType="com.tedu.DbDemo.pojo.Item">
SELECT category_id AS categoryId,item_name AS itemName FROM item
</select>
</mapper>

8.在controller包中创建ItemController类

package com.tedu.DbDemo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tedu.DbDemo.mapper.ItemMapper;
import com.tedu.DbDemo.pojo.Item;

@RestController
public class ItemController {
    
    
   @Autowired
   ItemMapper itemMapper;
   
   @RequestMapping("/item/select1")
   public List<Item> select1(Item item){
    
    
	   List<Item> itemList=itemMapper.select1(item); //打上断点
	   return itemList;
   }
}

Debug AS执行:
==> Preparing: SELECT category_id AS categoryId,item_name AS itemName FROM item
> Parameters:
<
Total: 3
在这里插入图片描述



9.动态SQL语句 ItemMapper.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">
<!-- namespace="接口的包名.接口名" -->
<mapper namespace="com.tedu.DbDemo.mapper.ItemMapper">

<!-- list<Item> select1() 
如果方法返回的是集合,resultType的值是集合中数据的类型
resultType指定的是结果集中的每一行转成那个类
参数item中有categroryId,itemName属性-->
<select id="select1" parameterType="com.tedu.DbDemo.pojo.Item" resultType="com.tedu.DbDemo.pojo.Item">
SELECT category_id AS categoryId,item_name AS itemName
FROM item
<!-- 写的是where,不传参数 生成的sql是from item where
     前面的参数不传,sql是from item where and item_name like
     解决方法是吧where改成<where>  -->
<where>
   <if test="categoryId!=null">
	<!-- category_id是列名 ,categoryId是参数item中的属性 -->
	category_id=#{categoryId}
</if>

   <if test="itemName != null">
   <!-- concat是mysql内置的函数,拼接字符串 -->
   and item_name like concat('%',#{itemName},'%')
</if>
</where>
</select>
</mapper>

Run As测试:
http://localhost:8080/item/select1?categoryId=1&itemName=新
在这里插入图片描述


错误一:
http://localhost:8080/item/select1
SQL: SELECT category_id AS categoryId ,item_name AS itemName FROM item where

错误二:
http://localhost:8080/item/select1?itemName=%E6%96%B0
SQL: SELECT category_id AS categoryId ,item_name AS itemName FROM item where and item_name like concat(’%’,?,’%’)



10 集合参数

动态sql生成in

Item,java增加itemld属性,增加set()、get()
ltemMapper接口中增加listselectByList(Listlist)
ItemMapper.xml增加select id=selectByList
生成生成in(2,3,4) in (2)

ItemController增加selectByList
在这里插入图片描述

测试sql

SELECT
item_id AS itemid,category_id AS categoryId,
item_name AS itemName
FROM item
WHERE item_id IN(2,3,4)


在这里插入图片描述


给Item增加一个itemId,get()set()
package com.tedu.DbDemo.pojo;
//对应Item表
public class Item {
    
    
	String itemName;//对应item_name列
	Integer itemId;
	Integer categoryId;
	//set(),get()

	public String getItemName() {
    
    
		return itemName;
	}
	public void setItemName(String itemName) {
    
    
		this.itemName = itemName;
	}
	public Integer getCategoryId() {
    
    
		return categoryId;
	}
	public void setCategoryId(Integer categoryId) {
    
    
		this.categoryId = categoryId;
	}
	public Integer getItemId() {
    
    
		return itemId;
	}
	public void setItemId(Integer itemId) {
    
    
		this.itemId = itemId;
	}
}

ItemMapper 类增加一个方法商品编号查询
package com.tedu.DbDemo.mapper;

import java.util.List;

import com.tedu.DbDemo.pojo.Item;

public interface ItemMapper {
    
    
   //参数item中可以包含categoryId,itemName
	//如果item中的某个属性值不为空,就根据属性值查找
	public List<Item> select1(Item item);
	//根据商品编号查询
	public List<Item> selectByList(List<Integer> list);
}

创建动态生成: ItemMapper.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">
<!-- namespace="接口的包名.接口名" -->
<mapper namespace="com.tedu.DbDemo.mapper.ItemMapper">

<!-- list<Item> select1() 
如果方法返回的是集合,resultType的值是集合中数据的类型
resultType指定的是结果集中的每一行转成那个类
参数item中有categroryId,itemName属性-->
<select id="select1" parameterType="com.tedu.DbDemo.pojo.Item" resultType="com.tedu.DbDemo.pojo.Item">
SELECT category_id AS categoryId,item_name AS itemName
FROM item
<!-- 写的是where,不传参数 生成的sql是from item where
     前面的参数不传,sql是from item where and item_name like
     解决方法是吧where改成<where>  -->
<where>
   <if test="categoryId!=null">
	<!-- category_id是列名 ,categoryId是参数item中的属性 -->
	category_id=#{categoryId}
</if>

   <if test="itemName != null">
   <!-- concat是mysql内置的函数,拼接字符串 -->
   and item_name like concat('%',#{itemName},'%')
</if>
</where>
</select>
<!-- public List<Item> selectByList(List<Integer> list); -->
<!-- parameterType parameterMap -->
<select id="selectByList" parameterType="Integer" resultType="com.tedu.DbDemo.pojo.Item">
SELECT
item_id AS itemid,category_id AS categoryId,
item_name AS itemName
FROM item
WHERE item_id IN
<!-- 生成(2,3,4) -->
<!-- foreach遍历集合
     collection指定集合的名称
     item指定从集合中取出的数据放在id中 -->
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
</mapper>
修改ItemController 类进行测试:
package com.tedu.DbDemo.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tedu.DbDemo.mapper.ItemMapper;
import com.tedu.DbDemo.pojo.Item;

@RestController
public class ItemController {
    
    
   @Autowired
   ItemMapper itemMapper;
   @RequestMapping("/item/selectByList")
	public List<Item> selectByList(){
    
    
		ArrayList<Integer> list=new ArrayList<Integer>();
		list.add(2);
		list.add(3);
		list.add(4);
		List<Item> itemList=itemMapper.selectByList(list);
		return itemList;
	}
	
   @RequestMapping("/item/select1")
   public List<Item> select1(Item item){
    
    
	   List<Item> itemList=itemMapper.select1(item);
	   return itemList;
   }
}

Run As执行
http://localhost:8080//item/selectByList?categoryId=1&itemName=新
在这里插入图片描述

小结:

在xml中通过标签生成sql
if标签、where标签、foreach标签



查看逆向工程生成的动态sql

找到mybatis02项目中的mapper包下UserMapper.xml

在这里插入图片描述

拓展:优化,使代码更加简洁

前面讲了CRUD的全部测试,下面是对CRUD示例的优化:

可以在配置文件中调用的地方都进行include引用

<sql id="cols">id,name,birthday,address</sql>

<select id="list" resultType="user">
	select <include refid="cols"/> from user
</select>

SQL中有特殊字符

当SQL中有特殊字符,mybatis不能正常解析时,用CDATA括起来就解决了

<![CDATA[ and age<=#{age} ]]>

总结

MVC和SSM的关系

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码。
在这里插入图片描述
Controller在小型项目中作用不明显,controller相当于厨师长,分配谁来做菜。

猜你喜欢

转载自blog.csdn.net/QQ1043051018/article/details/112857790