Mybatis增强&SSM集成

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Spursxuezhu/article/details/102727458

2.MyBatis原理回顾

MyBatis是一个ORM持久化框架,应用到系统持久层(Dao);
MyBatis可以使用xml或注解方式将接口或JAVA POJO映射成数据库中一条记录;
一个MyBatis的应用程序都以一个SqlSessionFactory 对象的实例为核心;
SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法

MyBatis是针对数据库交互的一个辅助框架,也是对jdbc做了的简单封装,以xml配置代替Java代码来管理数据库的交互细节!!

MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。

MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。

MyBatis使用回顾

3.2.1.加入MyBatis相关jar包

核心包,依赖包,数据库连接包
核心包 1个
依赖包 7个
数据库连接包 1个

添加核心配置文件
MyBatis-Config.xml:环境配置,映射配置

3.2.3.创建模型(Domain)

3.2.4.导入sql创建表

3.2.5.创建XxxMapper.xml文件,并配置在核心配置文件中

3.2.6.提取MyBatisUtils,创建单例会话工厂
在这里插入图片描述
3.2.7.实现Dao
在这里插入图片描述3.2.8.根据Dao需求,在mapper文件中添加sql
在这里插入图片描述
3.2.9.测试Dao

注意点
Mapper中package为dao接口的全类名

3.4.小结

准备:jar 核心配置文件
模型驱动:1个Domain + 1个Mapper.xml + 2个Dao(接口,实现)+测试类

SQL映射器Mapper

4.1.引入

MyBatis基于动态代理机制,让我们无需再编写Dao的实现。
传统Dao接口,现在名称统一以Mapper结尾,还有我们映射器配置文件要和映射器在同一个包.:
IDeptDao---->DeptMapper.java—DeptMapper.xml(namespace直接写DeptMapper.java的全限定名)
在这里插入图片描述
映射文件

<mapper namespace="cn.itsource.mybatis.mapper.UserMapper">
	<select parameterType=long” resultType=”User”>
Select * from t_user where id = #{id}
</select>
</mapper>

4.2.实现
接口实现方式一(传统):
在这里插入图片描述接口实现方式二(映射器):
在这里插入图片描述
4.3.使用映射器步骤

1、根据需求,创建模型相关的Mapper接口(UserMapper)
2、编写映射文件
a)Mapper。Xml的命名空间,必须和接口的“全限定名”一致
b)定义sql标签的id,需要和“接口的方法”一致
3、配置映射文件
4、测试

5.高级查询

5.1.需求
做员工高级查询,高级查询条件有两个:

1)关键字–作用于name或password
2)年龄区间(minAge,maxAge)-作用于age

5.2.实现

1)定义映射去接口-EmployeeMapper
List query(EmployeeQuery query);
2)写映射文件并且导入核心配置文件
3)做测试

注意:
1 where:里面所有的条件如果都在前面加上and,并且最后会把第一个and替换为where
2 if 判断条件是否满足,如果是并且用and
3 模糊查询
方案1: 不能用#
and ( name like %#{keywords}% or password like %#{keywords}% )
方案2:用$ sql注入
and ( name like ‘% k e y w o r d s {keywords}%' or password like '% {keywords}%’ )
方案3:用mysql中字符串拼接函数concat
and ( name like concat(’%’,#{keywords},’%’) or password like ‘%${keywords}%’ )
4 如果有特殊符号
方案1:转义符号
方案2:cdata
5 如果语句被多个地方调用可以使用sql include完成抽取和调用
5.3.测试

<?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="cn.itsource.dao.StudentDao">

   <select id="findAll" resultType="Student">

       select * from student


   </select>


    <insert id="save" parameterType="Student" useGeneratedKeys="true" keyColumn="id" keyProperty="id">

        insert into student (name,pwd,age) values (#{name},#{pwd},#{age})

    </insert>

    <delete id="delete" parameterType="long">

        delete from student where id = #{id}

    </delete>

    <update id="update" parameterType="Student">

        update student set name = #{name}, pwd = #{pwd} where id = #{id}

    </update>
    
    <insert id="insertBatch" parameterType="list">

        insert into student (name,pwd)
        values
        <foreach collection="list" item="item" separator=",">
            (#{item.name},#{item.pwd})
        </foreach>



    </insert>

    <delete id="deleteBatch" parameterType="list">

        delete from student where id

        in

        <foreach collection="list" item="item" separator="," open="(" close=")">

          #{item}

        </foreach>


    </delete>


    <select id="query" resultType="Student">

        select * from student
      <where>
          <if test="name!=null and name!=''">

              and name like CONCAT('%',#{name},'%')

          </if>

          <if test="pwd !=null and pwd != ''">

             and pwd = #{pwd}

          </if>

          <if test="minAge!=null and maxAge!=null">

              and age between #{minAge} and #{maxAge}

          </if>

      </where>


    </select>


package cn.itsource.test;

import cn.itsource.dao.StudentDao;
import cn.itsource.model.Student;
import cn.itsource.utils.MybatisUtis;
import cn.itsource.vo.StudentVo;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

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

public class MybatisTest {



    @Test
    public void testqueryall()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);

        List<Student> students = studentDao.findAll();

        for (Student student : students) {

            System.out.println(student);
        }
    }

    @Test
    public void testsave()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);
        for (int i = 0; i <10 ; i++) {

            Student student = new Student();

            student.setName("张无忌666");

            student.setPwd("123");

            student.setAge(18);

            studentDao.save(student);
        }

        session.commit();
    }

    @Test
    public void testdelete()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);

        studentDao.delete(9L);

        session.commit();
    }

    @Test
    public void testupdate()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);

        Student student = new Student();

        student.setId(1L);

        student.setName("周周");
        student.setPwd("999");

        studentDao.update(student);

        session.commit();
    }

    @Test
    public void testinsertBatch()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);

        List<Student> list = new ArrayList<>();

        for (int i = 0; i <10 ; i++) {

            Student student = new Student();

            student.setName(i+"周程");

            student.setPwd(i+"666");

            list.add(student);
        }

        studentDao.insertBatch(list);

        session.commit();

    }

    //批量删除

    @Test
    public void testdeletebatch()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);

        List<Integer> list = Arrays.asList(1, 2, 8);

        studentDao.deleteBatch(list);

        session.commit();

    }

    @Test
    public void testquery()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);

        StudentVo studentVo = new StudentVo();

        studentVo.setPwd("0666");

        List<Student> list = studentDao.query(studentVo);

        for (Student student : list) {
            System.out.println(student);
        }


    }

    @Test
    public void testquery2()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);

        StudentVo studentVo = new StudentVo();

        studentVo.setName("周");

        List<Student> list = studentDao.query(studentVo);

        for (Student student : list) {
            System.out.println(student);
        }
    }

    @Test
    public void testquery3()throws Exception{

        SqlSession session = MybatisUtis.getSession();

        StudentDao studentDao = session.getMapper(StudentDao.class);

        StudentVo studentVo = new StudentVo();

        studentVo.setMinAge(18);

        studentVo.setMaxAge(26);

        List<Student> list = studentDao.query(studentVo);

        for (Student student : list) {
            System.out.println(student);
        }
    }
}

6.结果映射(resultMap)

6.1.为什么要使用结果映射

解决表字段名和对象属性名不一样的情况.
关联对象查询,在mybatis不会默认查询出来,需要自己查询结果并且通过resultMap来配置

6.2.关联映射分类

一对一:一个员工只有一个身份证号。随意一方设计一个字段
多对一:多个员工对应一个部门。一般在多方设计一个一方属性 员工里面设计部门字段
一对多:一个部门拥有多个员工。还是在多方维护对象关联关系
多对多: 一个员工有多个角色。一个角色属于多个员工。用中间表来表示

本质上:多对一,一对一是一样的,都只是处理一个(association )。而一对多、多对多也是一样处理的都是集合(collection)

6.3.关联映射处理方式

MyBatis提供两种方式处理我们关联对象,嵌套查询和嵌套结果。
嵌套结果: 发送1条SQL,查询所有的信息(本身+关联对象)
嵌套查询:发送1+N条sql。
接下来,分别使用两种方式对多对一、一对一和一对多、多对多进行处理。

--  查询员工时要把一起获取到,sql怎么?
--  1 嵌套结果(一条SQL查询出来)
SELECT
	e.id,e.name,e.password,e.age, d.id did,d.name dname
FROM
	t_employee e
LEFT JOIN t_dept d ON e.dept_id = d.id
WHERE
	e.id = 1
-- 2 嵌套查询(1+N条sql)
 SELECT * from t_employee
 SELECT * from t_dept where id = 1

6.4.多对一、一对一

6.4.1.嵌套结果
发一条关联sql解决问题,映射文件Mapper结果的手动封装ResultMap
使用嵌套结果映射来处理重复的联合结果的子集。–这种方式,所有属性都要自己来!!
在这里插入图片描述6.4.2.嵌套查询

嵌套查询(发1查询user+N查询dept条sql解决问题,映射文件Mapper结果的自动封装ResultMap)

通过执行另外一个SQL映射语句来返回预期的复杂类型。
<association …>
<association …>
在这里插入图片描述
elect * from t_department where id = #{id}
在这里插入图片描述
在这里插入图片描述

6.5.一对多

员工和部门:
在部门方,需要查询到当前部门下的所有员工。----集合查询

在这里插入图片描述6.5.2.嵌套查询
在这里插入图片描述

7.延迟加载

在这里插入图片描述
在这里插入图片描述在这里插入图片描述8.缓存
8.1.什么是缓存
缓存是一种典型的“以空间换时间”的策略。
Mybatis缓存
MyBatis支持缓存:
一级缓存: SqlSession级别缓存,缓存对象存储周期为第一次获取,到sqlsession被销毁掉,或是sqlSession().clearCache();

二级缓存: SqlSessionFactory级别缓存,缓存对象存储周期为第一次获取,到SqlSessionFactory被销毁掉(应用停止了);

8.3.实现缓存

默认情况下,只开启一级缓存,如果需要开启二级缓存我们需要在Mapper.xml添加一个标签和在主配置文件中;
注意:需要缓存的对象,应该实现java.io.Serializable;
在这里插入图片描述

9.SSM集成

SpringMvc+Spring+Mybatis
框架集成核心
如果你的项目中,用到了Spring框架,那么其他框架主要就是和Spring集成!!
和Spring集成的核心思路
1、把当前框架的核心类,交给Spring管理
2、如果框架有事务,那么事务也要统一交给Spring管理

步骤:
Spring
Spring+SpringMVC
Spring+Mybtis
Spring+SpringMVC+Mybatis:管理事务

jar:今天以导入jar的方式,不是maven

9.3.Spring集成到MyBatis
jdbc.properties—>Datasource ---->SqlSessionFactory----扫描Repository—>事务管理器-开启注解事务

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
          http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--扫描service包-->
    <context:component-scan base-package="cn.itsource.service.impl"></context:component-scan>


    <!-- jdbc连接信息-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${db.driver}"></property>
        <property name="url" value="${db.url}"></property>
        <property name="username" value="${db.username}"></property>
        <property name="password" value="${db.password}"></property>
    </bean>

    <!--sqlsessionfactory交给spring管理-->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="typeAliasesPackage">
            <value>
                cn.itsource.model,
                cn.itsource.vo
            </value>
        </property>
        <!--扫描所有的mapper的xml-->
        <property name="mapperLocations" value="classpath:cn/itsource/dao/mapper/*.xml"></property>
    </bean>

    <!--扫描所有的dao接口交给spring容器方便我们注入-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="cn.itsource.dao"></property>
    </bean>

    <!--事务的管理 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--注解式事务-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>



</beans>

9.2.Spring+SpringMVC

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
          http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--扫描controller-->
    <context:component-scan base-package="cn.itsource.controller" />
    <!--静态资源处理-->
    <mvc:default-servlet-handler />
    <!--识别@requestMapper等注解支持-->
    <mvc:annotation-driven />
    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
</bean>

    <!--上传-->

</beans>

jdbc.properties

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql:///test0625
db.username=root
db.password=123456

log4j.properties

log4j.rootLogger=debug, stdout
#log4j.rootLogger=NONE
log4j.logger.cn.itsource=TRACE

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--1.1 spring容器初始化-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mybatis.xml</param-value>
    </context-param>

    <!--1.2 配置springmvc-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--/*会拦截所有包括jsp-->
        <!--/会拦截所有但是不包含jsp-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--
        post请求乱码解决
       get请求实在tomcat猫中配置
    -->
    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>



</web-app>

常见错误
10.1.写的mapper文件没有在配置文件里面注册
java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for cn.itsource.mybatis.crud.UserMapper.createTable

10.2.返回的结果是List,而需要的是一个对象
org.apache.ibatis.executor.ExecutorException: Statement returned more than one row, where no more than one was expected.

select id,name from t_dept where id=#{id}

10.3.没有序列化异常
org.apache.ibatis.cache.CacheException: Error serializing object. Cause: java.io.NotSerializableException: cn.itsource.MyBatisPlus.domain.User
Caused by: java.io.NotSerializableException: cn.itsource.MyBatisPlus.domain.User
指定对象不可序列化异常!

10.4.序列化原理
能够把java对象转变成二进制!!!!!!!!同时,能够从二进制还原成java对象!!
什么时候需要实现序列化??
1、在网络中直接传输一个java对象。(webservice)
2、在数据库的Blob字段(列)中,直接存一个java对象(医院cs系统)
3、当前,需要把java对象放入内存(本地的临时文件)中
java.io.ObjectInputStream
java.io.ObjectOutputStream
4.HttpSession里面存放对象,tomcat的内存不足的时候,钝化到硬盘

猜你喜欢

转载自blog.csdn.net/Spursxuezhu/article/details/102727458