MyBatis(2)

1.MyBatis的SQL映射文件

1.1增删改查标签

	<!-- 
	  标签属性:
	   id:identifier:唯一标识符,id值要和接口的方法名保持一致
	   parameterType:参数类型,该参数是可以省略的!
	   resultType:返回结果类型,和接口返回结果类型保持一致。
	 -->
	<select id="getProductById"  resultType="com.offcn.bean.Product">
	    select pid,p_name pName,color,price,description from product where pid= #{pid}
	</select>
	
	<insert id="saveProduct" >
	   insert into product(p_name,color,price,description) values(#{pName},#{color},#{price},#{description})
	</insert>
	
	<update id="updateProduct" >
	    update product set p_name = #{pName},price=#{price} where pid=#{pid}
	</update>
	
	<delete id="deleteProductByPid" >
	  delete from product where pid = #{pid}
	</delete>

注意点:
*对于增删改标签,必须提交事务:

  1. 手动提交:sqlSession.commit()
  2. 自动提交: sqlSessionFactory.openSession(true)

测试代码:

@Test
	public void testDelete() throws IOException {
		SqlSession sqlSession = sqlSessionFactory.openSession(true);
		ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);
	    mapper.deleteProductByPid(15);
		
		//4.关闭SqlSession对象
		sqlSession.close();	
	}

1.2Sql片段

	<!-- sql标签主要是做sql语句重用 -->
	<sql id="productSql">
	   p_name,color,price,description
	</sql>

引用即可:

	<select id="getProductById"   resultType="com.offcn.bean.Product">
	    select pid,<include refid="productSql"/> from product where pid= #{pid}
	</select>

2.在sql语句中如何获取各种各样的参数

 * 1.一个普通参数 :                     #{随便写}
 * 2.多个【两个及两个以上】普通参数 : 给每个参数前面加一个@param,在sql语句的#{}里面用@Param注解的value值取
 * 3.参数是一个POJO对象 :               #{对象的属性名}
 * 4.参数是一个Map :                    #{某个键}
 * 4.参数是一个POJO对象列表【List、Collection】: #{list[下标]}或者 #{collection[下标]}或者 #{param注解[下标]}
 * 5.参数是一个数组类型 :               #{array【下标】}
 * 6.参数是上面的任意组合 :              {param注解的value值,再通过.或者下标的方式去属性值或者元素值}

3.MyBatis接口的各种各样的返回值

 * 接口中各种各样的返回值:
 *  1.基本数据类型:int,Integer、double、Double、long、Long、boolean
 *     select: 需要在mapper接口中声明返回值类型,并且SQL映射文件中声明resultType属性
 *     insert、update、delete:只需要在mapper接口中声明返回值类型即可,在对应的SQL映射文件中不用声明resultType属性
 *  2.POJO对象
 *  3.POJO对象列表:
 *  4.Map集合:基本不用
 *              一行:
 *              多行:

3.1#{}与${}区别 [面试题]

#{}:类似于我们JavaWeb部分学过的PrepareStatement对象,采用占位符,
以预编译的方式执行sql语句的,是Sql安全的,不存在sql漏洞问题。

${}:类似于我们JavaWeb部分学过的statement对象,直接将参数拼接到sql语句中,
这种是存在sql漏洞问题。
实际开发中,一般都使用#{},但是在有些特殊情况下,就必须使用 , 比 如 获 取 表 名 、 排 序 字 段 、 l i k e 模 糊 查 询 , 就 必 须 使 用 {}, 比如获取表名、排序字段、like模糊查询,就必须使用 like使{}

3.2ResultMap标签

如果数据表的列名和pojo对象的属性名不对应时,怎么将表的列名映射到对象属性上?
一、起别名
二、在mybatis的全局配置文件中开启:mapUnderscoreToCamelCase=true
三、使用ResultMap标签

	<!-- resultMap 可以完成表的列名和pojo对象的属性名的映射 -->
	<resultMap type="com.offcn.bean.Product" id="getProductByIdResultMap">
	      <!-- id是用来映射主键的 -->
	      <id column="pid" property="pid"/> 
	      <!-- result标签是用来映射其它普通字段的 -->
	     <result column="p_name" property="pName"/>
	     <result column="price" property="price"/>
	     <result column="color" property="color"/>
	     <result column="description" property="description"/>
	</resultMap>
		<!-- resultType属性和resultMap 有且只能有一个属性存在 -->
	<select id="getProductById"  resultMap="getProductByIdResultMap">
	  select pid,p_name,price,color,description from product where pid = #{pid}
	</select>
resultMap作用:
  1.字段映射
  2.可以将表的关联关系直接映射pojo对象的关联关系。这个功能是resultType所不具

备的,resultType只能是处理单表映射。

4.关联关系映射

表与表之间关系:一对一、一对多、多对一、多对多

4.1x对一的关联关系映射

以多对一为例:讲解对一的关联关系映射
举例:员工对部门、订单项和订单
需求:在查询员工信息的时候,顺带着将该员工所属的部门信息查询查来。

4.1.1创建表
CREATE TABLE dept(
  did INT PRIMARY KEY AUTO_INCREMENT COMMENT '部门id',
  dept_name VARCHAR(30) NOT NULL COMMENT '部门名称'
)

CREATE TABLE emp(
  eid INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工id',
  ename VARCHAR(30) NOT NULL COMMENT '员工名称',
  did INT COMMENT '所属部门id',
  FOREIGN KEY(did) REFERENCES dept(did)
)
4.1.2创建实体类
public class Dept {//提供属性的getter/setter方法
	private Integer did;
	private String deptName;
}

public class Employee {//提供属性的getter/setter方法
 private Integer eid;
 private String ename;
 private Dept dept;
}
4.1.3创建接口和sql映射文件
public interface EmployeeMapper {
	 public Employee getEmployeeWithDeptByEid(Integer eid);
}
<?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.offcn.dao.EmployeeMapper">
	
</mapper>
4.1.4关联关系映射【三种解决方案】

第一种:给属性的属性赋值。【连缀】

<resultMap type="com.offcn.bean.Employee" id="getEmployeeWithDeptByEidResultMap">
	   <!-- 员工表数据的映射 -->
	   <id column="eid" property="eid"/>
	   <result column="ename" property="ename"/>
	   <!-- 部门表数据的映射 -->
	   <result column="did" property="dept.did"/>
	   <result column="dept_name" property="dept.deptName"/>
	</resultMap>

  <select id="getEmployeeWithDeptByEid" resultMap="getEmployeeWithDeptByEidResultMap">
        SELECT e.eid,e.ename,e.did,d.`dept_name`
		FROM emp e
		LEFT JOIN dept d
		ON e.`did` = d.`did`
		WHERE e.eid = #{eid}
  </select>

4.2x对多的关联关系映射[2种]

一对多:订单和订单项,部门和员工
多对多:老师和学生
以部门和员工为例,演示:
需求:在查询某个部门信息的时候,将该部门下的所有员工信息也查询出来。

4.2.1创建表
CREATE TABLE dept(
  did INT PRIMARY KEY AUTO_INCREMENT COMMENT '部门id',
  dept_name VARCHAR(30) NOT NULL COMMENT '部门名称'
)

CREATE TABLE emp(
  eid INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工id',
  ename VARCHAR(30) NOT NULL COMMENT '员工名称',
  did INT COMMENT '所属部门id',
  FOREIGN KEY(did) REFERENCES dept(did)
)
4.2.2创建实体类
public class Dept {
	private Integer did;
	private String deptName;
	private List<Employee> emps;//提供getter/setter方法
}

public class Employee { //提供getter/setter方法
 private Integer eid;
 private String ename;
}
4.2.3创建mapper接口和sql映射文件
public interface DeptMapper {
  Dept getDeptWithEmpsByDid(Integer did);
}
<?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.offcn.dao.DeptMapper">
</mapper>
4.2.4关联映射[2种解决方案]

第一种:在resultlMap标签内部采用collection标签

<resultMap type="com.offcn.bean.Dept" id="getDeptWithEmpsByDidResultMap">
    <id column="did" property="did"/>
    <result column="dept_name" property="deptName"/>
    
    <!-- 映射关联字段 
    collection:标签用于处理对多的关联关系
      property:指定关联属性
      ofType:指定集合中元素的数据类型
    -->
    <collection property="emps" ofType="com.offcn.bean.Employee">
        <id column="eid" property="eid"/>
        <result column="ename" property="ename"/>
    </collection>
</resultMap>

<select id="getDeptWithEmpsByDid" resultMap="getDeptWithEmpsByDidResultMap">
    SELECT d.`did`,d.`dept_name`,e.`eid`,e.`ename`
	FROM dept d
	LEFT JOIN emp e
	ON e.`did`=d.`did`
	WHERE d.`did` = #{did}
</select>

第二种:分步查询,resultMap标签内部采用collection标签

deptMapper.xml文件

	<resultMap type="com.offcn.bean.Dept" id="getDeptWithEmpsByDidResultMap">
	  <id column="did" property="did"/>
	  <result  column="dept_name" property="deptName"/>
	  <!-- 关联字段映射 -->
	  <collection property="emps" select="com.offcn.dao.EmployeeMapper.getEmpsByDid" column="did"></collection>
	</resultMap>
	
	<select id="getDeptWithEmpsByDid" resultMap="getDeptWithEmpsByDidResultMap">
		SELECT d.`did`,d.`dept_name`
		FROM dept d
		WHERE d.`did` = #{did}
	</select>

EmployeeMapper.xml

   <select id="getEmpsByDid" resultType="com.offcn.bean.Employee">
        SELECT e.eid,e.ename
	       	FROM emp e
		      WHERE e.did= #{dddd}
   </select>

补充:
多对多表的创建:

CREATE TABLE teacher(
  tid INT PRIMARY KEY AUTO_INCREMENT,
  tname VARCHAR(30) NOT NULL
);

CREATE TABLE student(
  sid INT PRIMARY KEY AUTO_INCREMENT,
  sname VARCHAR(30) NOT NULL
)

CREATE TABLE student_teacher(
  sid INT,
  tid INT,
  PRIMARY KEY(sid,tid),
  FOREIGN KEY(sid) REFERENCES student(sid),
  FOREIGN KEY(tid) REFERENCES teacher(tid)
)

5.MyBatis动态SQL

• if:类似于javaweb部分的c:if标签,做判断使用
• choose (when, otherwise): 类似于java基础的switch…case多分支判断语句。
• trim (where, set):where标签代替where关键字、set标签代替set关键字
• foreach:类似于javaweb部分学过的c:foreach标签,遍历一个集合或者数组的
动态sql在mybatis的SQL映射文件中使用。

5.1If

需求:如果用户输入了价格,就按着价格查询,如果用户输入了产品名称,就按着产品名称查询,如果这两个条件都输入了,我们就用这两个条件一起查询。

<select id="getProductList" resultType="com.offcn.bean.Product">
	    select pid,p_name pName,price,color,description 
	    from product 
	    where 
	     <if test="price >= 0">
	        price > #{price}
	     </if>
	     <if test="pName != null and pName != '' ">
	       and p_name like '%${pName}%'
	     </if>
	     <if test="pid != null">
	       and pid = #{pid}
	     </if>
	</select>

注意点:
不要&&,用and,实在想用,用这些特殊字符的实体名称,可以参考
在这里插入图片描述
MyBatis的SQL映射文件不支持直接使用<【小于号】,要想使用可以借助于<![CDATA[SQL语句]]>

select pid,p_name pName,price,color,description from product where <![CDATA[price < #{price}]]> and p_name like '%${pName}%' and pid = #{pid}

If标签这里存在bug,怎么解决?
两种解决方案:
第一种:在where后面加一个 1=1

select pid,p_name pName,price,color,description from product where 1=1 <![CDATA[and price < #{price}]]> and p_name like '%${pName}%' and pid = #{pid}

第二种解决方案:将where关键字换成where标签,where标签相当于where关键字,并且where标签可以将where标签内部所有sql拼接完毕之后的最前面的and或者or关键字去掉。

5.2Where标签

<select id="getProductList" resultType="com.offcn.bean.Product">
	    select pid,p_name pName,price,color,description 
	    from product 
	    <where>
		     <if test="price > 0">
		        <![CDATA[price < #{price}]]>
		     </if>
		     <if test="pName != null and pName != '' ">
		       and p_name like '%${pName}%'
		     </if>
		     <if test="pid != null">
		       and pid = #{pid}
		     </if>
	     </where>
	</select>

Where标签存在的问题是:只能将where内部拼接的sql语句最前面的and或者or关键字去除,并不能将where内部拼接的sql语句最后面的and或者or关键字去除。

5.3Trim

<!-- 
  trim标签:
    prefix:前缀,表示trim标签内部所有的sql拼接完毕之后,需要在最前面加的前缀
    prefixOverrides:前缀覆盖,表示trim标签内部所有的sql拼接完毕之后,用指定的prefixOverrides值将前面多余的关键字去除。
    suffix:后缀,表示trim标签内部所有的sql拼接完毕之后,需要在最后面加的后缀
    suffixOverrides:后缀覆盖,表示trim标签内部所有的sql拼接完毕之后,用指定的suffixOverrides值将最后面多余的关键字去除。

 -->
<select id="getProductList" resultType="com.offcn.bean.Product">
    select pid,p_name pName,price,color,description 
    <trim prefix="from product where" suffixOverrides="and">
	     <if test="price > 0">
	        <![CDATA[price < #{price}]]> and
	     </if>
	     <if test="pName != null and pName != '' ">
	        p_name like '%${pName}%' and
	     </if>
	     <if test="pid != null">
	        pid = #{pid}
	     </if>
     </trim>
    
</select>

5.4choose (when, otherwise)

需求:如果用户输入了产品的价格,就用价格查询,如果用户输入了产品的名称,就用名称查询,如果两个条件都带了,还是用价格查询
总结:choose(when、otherwise)它是有优先级的,只会走其中一个,一旦有满足条件的,执行完之后就退出了,不会执行后面的。

进行多分支判断:

<select id="getProductListWithChoose" resultType="com.offcn.bean.Product">
   select pid,p_name pName,price,color,description 
   from product 
   where
    <choose>
       <when test="price > 0">
          price > #{price}
       </when>
       <when test="pName != null and pName != '' ">
         p_name like '%${pName}%'
       </when>
       <otherwise>
         pid = #{pid}
       </otherwise>
    </choose>
    
</select>

5.5set

set标签是用来代替set关键字,可以将set标签内部最后面多出来的,【逗号】给去掉!

   <update id="updateProduct">
    update product 
    <set>
	    <if test="pName != null and pName != '' ">
	      p_name=#{pName}, 
	    </if>
	    <if test="price > 0">
	      price=#{price}
	    </if>
    </set> 
     where pid=#{pid}
   </update>

5.6foreach

批量查询:

  <select id="getProductWithForeach" resultType="com.offcn.bean.Product">
      select pid,p_name pName,price,color,description 
	  from product 
	  where pid in
	  <!-- foreach标签遍历集合或者数组
	         属性:
	         collection:表示要遍历的集合
	         item:表示将集合中的每个元素临时赋值给这个变量
	         separator:表示元素与元素之间的分隔符
	         open:当foreach标签遍历完集合或者数组之后,在拼接之后的sql最前面加的符号
	         close:当foreach标签遍历完集合或者数组之后,在拼接之后的sql最后面加的符号
	         index:表示该元素在集合中的索引值,一般不用
	   -->
	    <foreach collection="list" item="pid" separator="," open="(" close=")">
	      #{pid}
	    </foreach>
  </select>
  <select id="getProductWithForeachArray" resultType="com.offcn.bean.Product">
      select pid,p_name pName,price,color,description 
	  from product 
	  where pid in
	    <foreach collection="array" item="pid" separator="," open="(" close=")">
	      #{pid}
	    </foreach>
  </select>

批量插入:

  <insert id="batchInsert">
     INSERT INTO product(p_name,price,color,description) VALUES
     <foreach collection="list" item="pro" separator=",">
        (#{pro.pName},#{pro.price},#{pro.color},#{pro.description})
     </foreach>
  </insert>

批量删除:

6.MyBatis的运行流程

在这里插入图片描述

7.SSM整合

SSM:SpringMVC+Spring+MyBatis,简称SSM,
SSH: Struts2+Spring+Hibernate:简称SSH
整合效果:整合之后SpringMVC管理控制层,Spring管理Service,MyBatis管理Dao层。
在这里插入图片描述
具体步骤:

  • 第一步:导入jar包:springmvc+spring+mybatis+mybatis-spring.jar+mysql/c3p0+jstl
  • 第二步:在web.xml文件中配置spring的监听器【ContextLoaderListener】、springmvc的前
    端控制器、两个Filter
  • 第三步:创建springmvc.xml并配置
    扫描包【@Controller、@ControllerAdvice】
    配置内部资源视图解析器
    Mvc:default-servlet-handler标签
    Mvc:anntotation-driven
  • 第四步:创建applicationContext.xml并配置
    扫描包【除了加@Controller、@ControllerAdvice】
    加载properties配置文件信息
    配置数据源
    配置数据源事务管理器
    开启基于注解的事务支持
    配置SqlSessionFactoryBean对象
    DataSource:配置数据源
    configLocation:加载MyBatis全局配置文件
    配置MapperScannerConfigurer对象
    BasePackage:指定Mapper接口所在的包
  • 第五步:写测试代码,测试
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值