川职院-课堂笔记(2)5-27日起


每日笔记整理:

目录
  • 每日笔记整理:
    • 2022-05-27
    • 2022-05-29
      • SpringMVC文件上传
    • 2022-05-30
      • Spring+SpringMVC搭建流程
      • 构建第一个MyBatis项目
      • 入门版增删改查语句
      • 改写为sqlSession获取接口实现的实例
      • 封装MyBatis获取连接的工具类
    • 2022-05-31
      • mybatis核心配置文件
      • MapperXMLSQL映射文件配置
          • resultMap属性
          • resultType类型为map
          • 动态SQL标签
        • mybatis配置连接池(脱离web容器的方法)

2022-05-27

过滤器

依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。
使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
总之过滤器实际上就是对所有请求进行过滤操作,获取请求携带的数据或者修改请求的某些参数。

Spring-字符编码过滤器配置


  
    characterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
      
      encoding
      UTF-8
    
    
      
      forceEncoding
      true
    
  
  
    characterEncodingFilter
    /*
  

自定义过滤器

(1)创建一个自定义过滤器类,实现Filter接口

package com.huawei.sys.filter;

import javax.servlet.*;
import java.io.IOException;

/**
 * 测试过滤器类
 * 2022/5/27
 */
public class MyFilter implements Filter {

    /**
     * init 方法
     * 过滤器初始化的回调方法
     * 当容器初始化,过滤器也初始化,且只会初始化一次
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter-初始化!");
    }

    /**
     * doFilter 方法,拦截到请求后会执行的方法(每次请求一旦被拦截都会被调用)
     * @param servletRequest 网络io请求流
     * @param servletResponse 网络io响应流
     * @param filterChain filterChain.doFilter();//让过滤器通过拦截,放行请求
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        System.out.println("过滤器被调用!");

        filterChain.doFilter(servletRequest,servletResponse);//放行请求
        
    }

    /**
     * destroy 过滤器销毁的回调
     * 当容器销毁,过滤器就随之销毁
     */
    @Override
    public void destroy() {
        System.out.println("过滤器-销毁!");
    }
}

demo:拦截请求返回html代码

@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        System.out.println("过滤器被调用!");

        PrintWriter writer = servletResponse.getWriter();

        servletResponse.setCharacterEncoding("UTF-8");
        String html = "" +
                "" +
                "" +
                "" +
                "请求被过滤器阻止!";

        writer.println(html);

        //filterChain.doFilter(servletRequest,servletResponse);//放行请求

    }

(2)在web.xml文件中配置过滤器


  
    myFilter
    com.huawei.sys.filter.MyFilter
  
  
    myFilter
    /user/*
  

SpringMVC拦截器

是基于Java的jdk动态代实现的,实现HandlerInterceptor接口。不依赖于servlet容器,拦截器针对于contraller方法,并且能获取到所有的类,对类里面所有的方法实现拦截,粒度更小,拦截器中>可以注入service,也可以调用业务逻辑。

自定义拦截器方法

(1)定义一个类实现HandlerInterceptor接口

package com.huawei.sys.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义拦截器
 * 2022/5/27
 */
public class MyInterceptor implements HandlerInterceptor {

    /**
     * 在controller方法调用之前回调
     * @param request Http请求对象
     * @param response Http响应对象
     * @param handler 当前拦截器对象的实例
     * @return 需要返回一个布尔值:
     *              true  -》 拦截器放行
     *              false -》 拦截器阻止通行
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("1.在controller方法调用之前回调");

        return true;
    }

    /**
     * 在调用完成controller方法之后返回数据之前回调
     * @param request Http请求对象
     * @param response Http响应对象
     * @param handler 当前拦截器对象的实例
     * @param modelAndView 视图解析器需要接收的对象,可以定义要跳转的逻辑视图名以及包含要传送的数据
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        System.out.println("2.在调用完成controller方法之后返回数据之前回调");

        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);

    }

    /**
     * 当整个controller方法执行完成,且视图或者数据成功返回后回调
     * @param request Http请求对象
     * @param response Http响应对象
     * @param handler  当前拦截器对象的实例
     * @param ex 整个方法结束执行后可能没有成功会抛出异常,返回的异常对象
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("3.当整个controller方法执行完成,且视图或者数据成功返回后回调");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

(2)dispacther-servlet.xml配置文件中配置拦截器


    
    
        
        

        
        
            
            
            
            
        
    

2022-05-29

SpringMVC文件上传

(1)引入依赖


    
      org.apache.commons
      commons-lang3
      3.4
    
    
      commons-fileupload
      commons-fileupload
      1.3.1
    

    
      commons-io
      commons-io
      2.4
    

(2)在dispachter-servlet.xml配置文件中配置文件上传选项


    
        
        
        
        
    

(3)前端编写表单上传文件


(4)后端编写一个接收文件上传的pojo对象类

package com.huawei.sys.dto;

import lombok.Data;
import org.springframework.web.multipart.MultipartFile;

/**
 * 用于接收上传文件的类
 * 2022/5/29
 */
@Data
public class FileDto {

    private MultipartFile uploadFile;//上传的文件对象
    
    private String descs;//文件描述字段

}

(5)编写Controller方法接收文件上传的请求

package com.huawei.sys.controller;

import com.huawei.sys.dto.FileDto;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件上传和下载操作类
 * 2022/5/29
 */

@Controller
@RequestMapping("/file")
public class FileController {

    @RequestMapping(value = "/uploadOneFile",method = RequestMethod.POST)
    @ResponseBody
    public Map uploadOneFile(FileDto file){

        //默认保存上传文件的服务器地址
        String savePath = "F://fileupload";

        //1.取得上传的文件对象
        MultipartFile uploadFile = file.getUploadFile();

        //2.获取文件的名称
        String originalFilename = uploadFile.getOriginalFilename();

        System.out.println("上传的文件名:"+originalFilename);

        //3.将文件保存到目标路径中(封装一个File文件对象)
        /**
         * new File(文件保存的文件位置,文件名称(一定要带后缀))
         */
        File saveFile = new File(savePath,originalFilename);

        //返回数据的Map对象
        Map resMap = new HashMap<>();

        //4.调用MulitpartFile对象的tansferTo方法进行文件上传
        try {
            uploadFile.transferTo(saveFile);

            resMap.put("code","0000");
            resMap.put("msg","文件上传成功!");
        } catch (IOException e) {
            System.err.println("文件上传出错!");
            resMap.put("code","9999");
            resMap.put("msg","文件上传失败!");
            e.printStackTrace();
        }

        return resMap;
    }

}

文件下载
(1)Servlet3.0的方法下载文件

 /**
     * 下载文件(单文件下载)
     * @param fileName 要下载的文件名称
     * @param response 响应对象
     * @return
     */
    @RequestMapping("/fileDownLoad")
    public String downLoadFile(String fileName, HttpServletResponse response) throws IOException {

        //服务器文件保存位置
        String savePath = "F://fileupload";

        //1.设置响应头的参数
        response.setHeader("Content-Type","application/x-msdownload");
        response.setHeader("Content-Disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));

        //2.文件字节流读取文件
        String downLoadFilePath = savePath + "//"+fileName;//拼装出要下载的文件路径
        //获取文件字节输入流对象(服务中获取文件信息的io流)
        FileInputStream fileInputStream = new FileInputStream(downLoadFilePath);

        //3.通过响应对象获取输出流对象(服务器输出到客户端的io流)
        ServletOutputStream outputStream = response.getOutputStream();

        //4.通过io流输出文件
        //创建一个字节数组
        byte [] fileByte = new byte[fileInputStream.available()];

        fileInputStream.read(fileByte);//把读取的内容赋值到字节数组中

        //通过输出流输出
        outputStream.write(fileByte);

        //输出流
        outputStream.flush();
        outputStream.close();
        fileInputStream.close();

        return null;
    }

(2)SpringMVC的使用commons-io的下载方式

/**
     * SpringMVC文件下载
     * @param fileName 要下载的文件名称
     * @return
     */
    @RequestMapping("/filed2")
    public ResponseEntity downloadFile2(String fileName) throws IOException {

        //服务器文件保存位置
        String savePath = "F://fileupload";

        //1.创建一个Http响应头对象
        HttpHeaders headers = new HttpHeaders();

        //2.创建文件对象(要下载的文件)
        File file = new File(savePath,fileName);

        //设置响应头的参数
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", URLEncoder.encode(fileName,"UTF-8"));

        return new ResponseEntity(FileUtils.readFileToByteArray(file),
                headers, HttpStatus.CREATED);

    }

2022-05-30

Spring+SpringMVC搭建流程

(1)maven依赖整理

<?xml version="1.0" encoding="UTF-8"?>


  4.0.0

  com.huawei
  CZ_SpringMVCDemo1
  1.0.0
  
  war

  CZ_SpringMVCDemo1 Maven Webapp
  
  http://www.example.com

  
    UTF-8
    1.7
    1.7
    
    5.2.3.RELEASE
  

  

    
    
      org.springframework
      spring-web
      ${springBBH}
    
    
      org.springframework
      spring-webmvc
      5.2.3.RELEASE
    
    
      org.springframework
      spring-context
      5.2.3.RELEASE
    

    
      org.springframework
      spring-test
      5.2.3.RELEASE
    
    
      org.springframework
      spring-jdbc
      5.2.3.RELEASE
    
    
      org.aspectj
      aspectjweaver
      1.8.9
    
    
    
      junit
      junit
      4.11
      test
    
    
    
      org.slf4j
      slf4j-log4j12
      1.7.21
    
    
    
      javax.servlet
      javax.servlet-api
      3.1.0
    
    
      javax.servlet.jsp
      jsp-api
      2.2
    
    
      javax.servlet
      jstl
      1.2
    
    
    
      mysql
      mysql-connector-java
      8.0.22
    

    
    
      com.alibaba
      fastjson
      1.2.78
    

    
    
      org.apache.commons
      commons-lang3
      3.4
    
    
      commons-fileupload
      commons-fileupload
      1.3.1
    

    
      commons-io
      commons-io
      2.4
    

    
    
      org.projectlombok
      lombok
      1.18.22
      provided
    

    
    
      com.fasterxml.jackson.core
      jackson-core
      2.12.3
    
    
    
      com.fasterxml.jackson.core
      jackson-databind
      2.12.3
    

    
    
      javax.validation
      validation-api
      1.1.0.Final
    
    
      org.jboss.logging
      jboss-logging
      3.1.0.CR2
    
    
      org.hibernate
      hibernate-validator
      5.1.0.Final
    


  

  
  
    CZ_SpringMVCDemo1

    
    
      
        src/main/resources
        
        
          **/*.properties
          **/*.xml
          **/*.js
          **/*.css
          **/*.html
        
        false
      
      
        src/main/java
        
          **/*.properties
          **/*.xml
          **/*.js
          **/*.css
          **/*.html
        
        false
      
    

    
      
        
          maven-clean-plugin
          3.1.0
        
        
        
          maven-resources-plugin
          3.0.2
        
        
          maven-compiler-plugin
          3.8.0
        
        
          maven-surefire-plugin
          2.22.1
        
        
          maven-war-plugin
          3.2.2
        
        
          maven-install-plugin
          2.5.2
        
        
          maven-deploy-plugin
          2.8.2
        
      
    
    
      
        org.apache.maven.plugins
        maven-compiler-plugin
        
          8
          8
        
      
    
  


(2)配置web.xml




  
  Archetype Created Web Application
  
  
    contextConfigLocation
    classpath*:applicationContext.xml
  
  
  
    org.springframework.web.context.ContextLoaderListener
  

  
  
    dispatcher
    org.springframework.web.servlet.DispatcherServlet
    
    
      contextConfigLocation
      classpath:dispatcher-servlet.xml
    

    
    1
  
  
  
    dispatcher
    /
  

  
  
    hiddenHttpMethodFilter
    org.springframework.web.filter.HiddenHttpMethodFilter
  
  
    hiddenHttpMethodFilter
    /*
  

  
  
    characterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
      
      encoding
      UTF-8
    
    
      
      forceEncoding
      true
    
  
  
    characterEncodingFilter
    /*
  




(3)视图解析器配置文件必要配置项目

<?xml version="1.0" encoding="UTF-8"?>


    
    

    
    
        
        
    
    
    
    
    

    
    
        
        
        
        
    

    
    
        
            
            
                
            
        
    

(4)包结构定义规则

父级:公司域名反写(com.huawei)

? 业务包名(sys)

? 控制器层(controller)

? 数据转换层(dto)

? 业务接口层(service)

? 业务接口实现层(impl)

? 工具包(util)

? 过滤器(filters)

? 拦截器(interceptors)

? 配置类(configs)

构建第一个MyBatis项目

(1)在resouces目录下创建一个mybatis配置文件

名称可以自定义

<?xml version="1.0" encoding="UTF-8" ?>



    
    
        
                
                
                
                
                
                
            
        
    

    

(2)创建一个数据表

如:我创建一个学生表

CREATE TABLE `student`  (
  `code` varchar(20)  NOT NULL COMMENT '编号',
  `name` varchar(20)  COMMENT '姓名',
  `age` int(3)  COMMENT '年龄',
  PRIMARY KEY (`code`)
) ;

(3)创建一个与数据库字段相同的映射javaPOJO类

package com.huawei.dto;

import lombok.Data;

/**
 * 与数据库Student表实现映射的类
 * 2022/5/30
 */
@Data
public class StudentDo {

    private String code;

    private String name;

    private Integer age;

}

(4)在项目路径中创建一个dao包

dao包就是存放myBatis操作的代码

在dao包中创建接口,接口的目的就是解耦sql操作与业务操作之间的关系,命名规则为:业务+Mapper

/**
 * Mybatis映射接口层
 * 2022/5/30
 */
public interface StudentMapper {

    //根据学生编号查询学生数据
    StudentDo getStudentByCode(String code) throws IOException;

}

(5)编写映射xml文件

在项目目录下创建文件夹mybatis,将文件夹设置为资源文件路径

创建xml文件,命名规则为:业务名+Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>





    
    


#{} 是预编译处理,像传进来的数据会加个" "( #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号)
${} 就是字符串替换。直接替换掉占位符。$方式一般用于传入数据库对象,例如传入表名.
使用 ${} 的话会导致 sql 注入。所以为了防止 SQL 注入,能用 #{} 的不要去用 ${}
果非要用 ${} 的话,那要注意防止 SQL 注入问题,可以手动判定传入的变量,进行过滤,一般 SQL 注入会输入很长的一条 SQL 语句

(6)在mybatis配置文件中配置xml映射文件



    
        
    

(7)编写接口的实现类

package com.huawei.dao;

import com.huawei.dto.StudentDo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * mybatis自定义接口的实现类
 * 2022/5/30
 */
public class StudentMapperImpl implements StudentMapper{


    @Override
    public StudentDo getStudentByCode(String code) throws IOException {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        //4.通过数据库连接对象调用mybatis映射文件中的sql方法
        StudentDo studentDo = sqlSession.selectOne("StudentMapXML.getStudentByCode", code);

        System.out.println(studentDo);

        //5.归还连接(关闭连接)
        sqlSession.close();

        return studentDo;
    }
}

入门版增删改查语句

(1)接口中方法定义

/**
 * Mybatis映射接口层
 * 2022/5/30
 */
public interface StudentMapper {

    //根据学生编号查询学生数据
    StudentDo getStudentByCode(String code) throws IOException;

    //查询出多行学生数据
    List getStudentList() throws IOException;

    //新增学生信息(增、删、改-》返回的都是受影响的行数)
    int addStudent(StudentDo student) throws IOException ;

    //修改学生信息
    int updateStudent(StudentDo student) throws IOException ;

    //删除学生信息
    int deleteStudent(String code) throws IOException ;

}

(2)xml映射文件sql编写

<?xml version="1.0" encoding="UTF-8"?>





    
    

    
    

    
    
        INSERT into student VALUES(#{code},#{name},#{age})
    

    
    
        update student set name=#{name},age=#{age} where code=#{code}
    

    
    
        delete from student where code = #{code}
    


(3)接口实现类实现方法

package com.huawei.dao;

import com.huawei.dto.StudentDo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * mybatis自定义接口的实现类
 * 2022/5/30
 */
public class StudentMapperImpl implements StudentMapper{


    @Override
    public StudentDo getStudentByCode(String code) throws IOException {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        //4.通过数据库连接对象调用mybatis映射文件中的sql方法
        StudentDo studentDo = sqlSession.selectOne("StudentMapXML.getStudentByCode", code);

        System.out.println(studentDo);

        //5.归还连接(关闭连接)
        sqlSession.close();

        return studentDo;
    }

    @Override
    public List getStudentList() throws IOException {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        List objects = sqlSession.selectList("StudentMapXML.getStudentList");

        for(StudentDo studentDo:objects){
            System.out.println(studentDo);
        }

        return objects;
    }

    @Override
    public int addStudent(StudentDo student) throws IOException  {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        int insert = sqlSession.insert("StudentMapXML.addStudent", student);

        System.out.println("新增【"+insert+"】行");

        sqlSession.commit();//提交事务

        return 0;
    }

    @Override
    public int updateStudent(StudentDo student)  throws IOException {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        int update = sqlSession.update("StudentMapXML.updateStudent", student);

        System.out.println("修改【"+update+"】行");

        sqlSession.commit();//提交事务
        return 0;
    }

    @Override
    public int deleteStudent(String code)  throws IOException {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        int delete = sqlSession.delete("StudentMapXML.deleteStudent", code);

        System.out.println("删除【"+delete+"】行");

        sqlSession.commit();//提交事务
        return 0;
    }
}

改写为sqlSession获取接口实现的实例

调用mybatis映射xml中的sql方法,改写为面向接口调用的方法

@Override
    public List getStudentList() throws IOException {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        //4.获取接口对象 !!!!!!!   重点改变的位置  !!!!!!!
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        List studentList = mapper.getStudentList();

        return studentList;
    }

所以在这基础上,我们发现可以不用编写接口实现层,直接让mybatis完成实现调用

比如:在测试类中我们把接口实现层删掉,直接获取接口对象调用方法,它就会自动关联调用xml中的sql方法了

 @Test
    public void test1() throws IOException {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        //通过接口字节码文件对象获取接口的实例
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        List studentList = mapper.getStudentList();

        for(StudentDo studentDo:studentList){
            System.out.println(studentDo);
        }


    }

封装MyBatis获取连接的工具类

目的:减少创建工厂、获取连接的重复代码

package com.huawei.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * 获取mybatis数据连接的工具包
 * 2022/5/30
 */
public class SqlSessionUtil {

    //定义一个类常量:保证工厂类只有一个实例
    private final static SqlSessionFactory FACTORY;

    private SqlSessionUtil(){}

    //静态代码块
    static{

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");
        } catch (IOException e) {
            System.err.println("MyBatis配置文件加载错误!");
            e.printStackTrace();
        }

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        FACTORY = new SqlSessionFactoryBuilder().build(resourceAsStream);

    }

    /**
     * 获取mybatis连接对象
     * @return sqlSession对象
     */
    public static SqlSession getSqlSession(){
        return FACTORY.openSession(true);
    }


}

测试:

@Test
    public void test1() throws IOException {

        //省略之前复杂的声明过程,直接调用工具类中的方法来获取即可
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        //通过接口字节码文件对象获取接口的实例
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        List studentList = mapper.getStudentList();

        for(StudentDo studentDo:studentList){
            System.out.println(studentDo);
        }


    }

2022-05-31

mybatis核心配置文件

(1)properties配置标签

引入外部资源,注意顺序


    
    
    ... ...

外部配置文件

#这个是mybatis的配置属性文件
#mysql驱动
driver=com.mysql.cj.jdbc.Driver
#mysql的服务器连接地址
url=jdbc:mysql://localhost:3306/huawei?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
#用户名
userName=root
#密码
pwd=root123456

(2) settings 配置标签

settings 元素的作用是设置一些非常重要的设置选项,用于设置和改变 MyBatis 运行中的行为

比如日志:

 
    
        
        
    

然后在resources文件夹下创建log4j.properties配置文件

######################## ????DEBUG????????consoleh?file?????, console?file?????????
log4j.rootLogger=DEBUG,console,file

########################??????????
log4j.appender.console = org.apache.log4j.ConsoleAppender
#??????
log4j.appender.console.Target = System.out
#?DEBUG????
log4j.appender.console.Threshold = DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
#????
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

######################??????
log4j.logger.org.mybatis=DEBUG   
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

(3)typeAliases配置标签

给java中数据库与实体映射的类编写别名,以简化映射xml文件中返回值或者参数的编写

1.在typeAliases标签中直接配置typeAlias字标签,一个类一个标签的配置

在mybatis配置文件中


    
        
        
    

在映射xml中就可以编写别名了



    
    
    
    ... ...

2.自动扫描包下的pojo类生成别名

配置了 typeAliases 元素,在 Mapper.xml 中的 resultType 属性无须写完全限定名com.huawei.pojo.User,只需要写 User 或 user 不区分大小写。


    
        
        
    

(4)environments环境配置标签


    
    
        
                
                
                
                
                
                
            
        
    

(5)mapper映射文件配置标签

在之前的学习中,我们是一个xml映射文件编写一个mapper标签

今天,我们学习自动扫描包完成映射。

注意:这种方式必须保证接口名和 SQL 映射文件名相同,还必须在同一个包中。
如:

mybatis配置文件中的配置方法


    
        
        
    

此时测试调用可能会出现异常:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.huawei.dao.StudentMapper.getStudentList

原因是:xml文件是一个静态文件,且现如今被放置在java源代码目录中,默认情况下idea是会自动排除静态文件进行打包,所以要配置maven静态文件也进行打包:

pom.xml文件中进行配置


    CZ_MyBatisDemo1

    
    
      
        src/main/resources
        
        
          **/*.properties
          **/*.xml
          **/*.js
          **/*.css
          **/*.html
        
        false
      
      
        src/main/java
        
          **/*.properties
          **/*.xml 
          **/*.js
          **/*.css
          **/*.html
        
        false
      
    
    ... ...

配置完成之后,使用maven工具-》clean-》install,观察是否成功打包

MapperXMLSQL映射文件配置

(1)Select标签


resultMap属性

作用:实现不同名字段和属性实现关联映射赋值


    
        
        
        
        
    

    
    
resultType类型为map

在接口中定义方法

//查询出所有的学生信息放回map集合
    List> getAllStudentData() throws IOException;

xml中编写sql


动态SQL标签

(1)if标签


    

执行结果,根据传递参数的值判断是否拼接if标签中的sql语句

[com.huawei.dao.StudentMapper.getStudentList]-==>  Preparing: select * from student where 1=1 and userName = ? and age = ?
[com.huawei.dao.StudentMapper.getStudentList]-==> Parameters: 张三(String), 47(Integer)
[com.huawei.dao.StudentMapper.getStudentList]-<==      Total: 0

(2)if+where 标签结合

我们有多个条件时,不知道那个回是第一个条件,因为第一个条件前sql要拼接上where关键字,此时可以如下使用,mybatis会自动判断字段先后添加where关键字


    

(3)在使用更新语句时可以使用set+if标签动态update语句

/*更新接口方法*/
//修改学生信息
    int updateStudent(StudentDo studentDo);

sql映射xml文件


    
        update student
        
            
                userName = #{name},
            
            
                age = #{age},
            
        
        where code = #{code}
    

(4)分支条件标签choose+when+otherwise


(5)foreach循环sql

1.单参数传入list集合的情况

接口定义

//查询学生的编号是否在集合中出现过
    List getStudentListByCodeList(List codes);

sql映射文件xml


    

2.单参数传入数组的情况

接口定义

//查询学生的编号是否在数组中出现过
    List getStudentListByCodeList(String [] codes);

sql映射文件xml

!--查询学生的编号是否在集合中出现过 -->
    

执行sql拼接效果

[com.huawei.dao.StudentMapper.getStudentListByCodeList]-==>  Preparing: select * from student where code in ( ? , ? , ? , ? , ? )
[com.huawei.dao.StudentMapper.getStudentListByCodeList]-==> Parameters: 1(String), 2(String), 3(String), 10(String), 12(String)

3.传入一个对象或者map集合,遍历对象中的集合属性或者map中的集合元素

此案例以map元素演示:

接口定义:

//查询学生的编号是否在数组中出现过
    List getStudentListByCodeList(Map map);

sql映射xml


    

测试调用

@Test
    public void test1() throws IOException {

        //1.加载mybatis配置文件-得到输入流对象
        InputStream resourceAsStream = Resources.getResourceAsStream("myBatisConfig.xml");

        //2.根据配置文件流对象加载出SqlSessionFactory工厂对象(SqlSessionFactory生产连接对象)
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3.获取数据库连接-SqlSession (类似JDBC中的Connect对象)
        SqlSession sqlSession = factory.openSession();

        //4.通过数据库连接对象调用mybatis映射文件中的sql方法
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        //设置查询参数
        Map map = new HashMap<>();

        List codes = new ArrayList<>();

        codes.add("1");
        codes.add("2");
        codes.add("3");
        codes.add("4");
		//!!!!! 重点 !!!!!!
        map.put("codeList",codes);


        mapper.getStudentListByCodeList(map);

        //5.归还连接(关闭连接)
        sqlSession.close();
    }

mybatis配置连接池(脱离web容器的方法)

(1)引入druid连接池依赖



    com.alibaba
    druid
    1.2.8
    compile


(2)更换连接池的第一步-创建一个工厂类继承PooledDataSourceFactory

/**
 * 创建一个自定义的工厂类,继承PooledDataSourceFactory
 * 重新编写DataSource对象的创建方法
 * 2022/5/31
 */
public class MyDruidPoolFactory extends PooledDataSourceFactory {

    /**
     * 定义构造器,替换dataSource对象的创建方法
     */
    public MyDruidPoolFactory(){
        this.dataSource = new DruidDataSource();
    }
    
}

(3)更换mybatis配置文件中-环境配置数据源标签的type属性

 
    
        
                
                
                
                
                
                
                
                
            
        
    

相关