欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java之mybatis详解

程序员文章站 2022-07-11 10:34:09
文章大纲 一、mybatis介绍二、mybatis代码实战三、项目源码下载四、参考文章 一、mybatis介绍 1. mybatis是什么? mybatis是一个持久层的框架,是apache下的*项目。mybatis托管到goolecode下,再后来托管到github下(https://githu ......

文章大纲

一、mybatis介绍
二、mybatis代码实战
三、项目源码下载
四、参考文章

 
Java之mybatis详解

一、mybatis介绍

1. mybatis是什么?

  mybatis是一个持久层的框架,是apache下的*项目。mybatis托管到goolecode下,再后来托管到github下(https://github.com/mybatis/mybatis-3/releases)。
  mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,*灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。
  mybatis可以将向 preparedstatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)

2. mybatis框架图解

 
Java之mybatis详解

二、mybatis代码实战

1. 创建maven的javaweb项目

文章重点在于讲解spring mvc功能,因此创建项目方式不进行深入讲解,创建后的项目目录如下:

 
Java之mybatis详解

2. 创建数据库表

表名为:mybatis,表结构如下:

 
Java之mybatis详解

3. springmvc、mybatis基本配置

3.1 pom.xml添加maven相关依赖

<project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelversion>4.0.0</modelversion>
  <groupid>mabatis_demo</groupid>
  <artifactid>mabatis_demo</artifactid>
  <version>0.0.1-snapshot</version>
  <packaging>war</packaging>
  <name/>
  <description/>

  <properties>
    <project.build.sourceencoding>utf-8</project.build.sourceencoding>
    <!-- spring版本号 -->
    <spring.version>4.2.5.release</spring.version>

    <!-- mybatis版本号 -->
    <mybatis.version>3.2.8</mybatis.version>

    <!-- mysql驱动版本号 -->
    <mysql-driver.version>5.1.29</mysql-driver.version>

  </properties>

  <dependencies>

    <dependency>
      <groupid>com.google.code.gson</groupid>
      <artifactid>gson</artifactid>
      <version>2.8.2</version>
    </dependency>

    <!-- 添加mybatis依赖 -->
    <dependency>
      <groupid>org.mybatis</groupid>
      <artifactid>mybatis</artifactid>
      <version>${mybatis.version}</version>
    </dependency>

    <!-- 添加mybatis/spring整合包依赖 -->
    <dependency>
      <groupid>org.mybatis</groupid>
      <artifactid>mybatis-spring</artifactid>
      <version>1.2.2</version>
    </dependency>

    <!-- 添加mysql驱动依赖 -->
    <dependency>
      <groupid>mysql</groupid>
      <artifactid>mysql-connector-java</artifactid>
      <version>${mysql-driver.version}</version>
    </dependency>


    <dependency>
      <groupid>org.apache.openejb</groupid>
      <artifactid>javaee-api</artifactid>
      <version>5.0-1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupid>javax.servlet</groupid>
      <artifactid>jstl</artifactid>
      <version>1.2</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupid>javax.servlet.jsp</groupid>
      <artifactid>jsp-api</artifactid>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>
    <!-- 分页 -->
    <dependency>
      <groupid>com.github.pagehelper</groupid>
      <artifactid>pagehelper</artifactid>
      <version>4.1.4</version>
    </dependency>

    <!--测试包-->
    <dependency>
      <groupid>junit</groupid>
      <artifactid>junit</artifactid>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <!-- c3p0数据库连接池 -->
    <dependency>
      <groupid>c3p0</groupid>
      <artifactid>c3p0</artifactid>
      <version>0.9.1.2</version>
    </dependency>

    <!-- commons工具包 -->

    <!--图片上传相关的-->
    <dependency>
      <groupid>commons-fileupload</groupid>
      <artifactid>commons-fileupload</artifactid>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupid>commons-io</groupid>
      <artifactid>commons-io</artifactid>
      <version>2.6</version>
    </dependency>


    <dependency>
      <groupid>commons-beanutils</groupid>
      <artifactid>commons-beanutils</artifactid>
      <version>1.7.0</version>
    </dependency>
    <dependency>
      <groupid>commons-codec</groupid>
      <artifactid>commons-codec</artifactid>
      <version>1.7</version>
    </dependency>
    <dependency>
      <groupid>org.apache.commons</groupid>
      <artifactid>commons-io</artifactid>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupid>commons-collections</groupid>
      <artifactid>commons-collections</artifactid>
      <version>3.2</version>
    </dependency>
    <dependency>
      <groupid>commons-net</groupid>
      <artifactid>commons-net</artifactid>
      <version>3.0</version>
    </dependency>
    <dependency>
      <groupid>org.apache.commons</groupid>
      <artifactid>commons-math3</artifactid>
      <version>3.2</version>
    </dependency>
    <dependency>
      <groupid>commons-validator</groupid>
      <artifactid>commons-validator</artifactid>
      <version>1.4.0</version>
    </dependency>
    <dependency>
      <groupid>commons-httpclient</groupid>
      <artifactid>commons-httpclient</artifactid>
      <version>3.1</version>
    </dependency>
    <dependency>
      <groupid>commons-dbcp</groupid>
      <artifactid>commons-dbcp</artifactid>
      <version>1.4</version>
    </dependency>
    <dependency>
      <groupid>commons-logging</groupid>
      <artifactid>commons-logging-api</artifactid>
      <version>1.1</version>
    </dependency>
    <dependency>
      <groupid>commons-pool</groupid>
      <artifactid>commons-pool</artifactid>
      <version>1.6</version>
    </dependency>


    <!-- 添加spring核心依赖 -->
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-core</artifactid>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-web</artifactid>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-oxm</artifactid>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-tx</artifactid>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-jdbc</artifactid>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-webmvc</artifactid>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-context</artifactid>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-context-support</artifactid>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-aop</artifactid>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupid>org.springframework</groupid>
      <artifactid>spring-test</artifactid>
      <version>${spring.version}</version>
    </dependency>



    <dependency>
      <groupid>org.apache.httpcomponents</groupid>
      <artifactid>httpclient</artifactid>
      <version>4.5.2</version>
    </dependency>
    <dependency>
      <groupid>dom4j</groupid>
      <artifactid>dom4j</artifactid>
      <version>1.6.1</version>
    </dependency>
    <dependency>
      <groupid>org.apache.shiro</groupid>
      <artifactid>shiro-core</artifactid>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupid>org.apache.httpcomponents</groupid>
      <artifactid>httpmime</artifactid>
      <version>4.5.2</version>
    </dependency>

    <dependency>
      <groupid>com.thoughtworks.xstream</groupid>
      <artifactid>xstream</artifactid>
      <version>1.4.9</version>
    </dependency>

    <!-- 日志相关工具类导入 -->
    <dependency>
      <groupid>ch.qos.logback</groupid>
      <artifactid>logback-classic</artifactid>
      <version>1.1.7</version>
    </dependency>

    <dependency>
      <groupid>ch.qos.logback</groupid>
      <artifactid>logback-core</artifactid>
      <version>1.1.7</version>
    </dependency>



    <!-- validation校验-->
    <dependency>
      <groupid>javax.validation</groupid>
      <artifactid>validation-api</artifactid>
      <version>1.1.0.final</version>
    </dependency>
    <!-- validation校验-->
    <dependency>
      <groupid>org.hibernate</groupid>
      <artifactid>hibernate-validator</artifactid>
      <version>5.4.0.final</version>
    </dependency>

    <!-- junit.jar -->
    <dependency>
      <groupid>junit</groupid>
      <artifactid>junit</artifactid>
      <version>4.10</version>
    </dependency>

  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupid>org.apache.maven.plugins</groupid>
        <artifactid>maven-compiler-plugin</artifactid>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>

    <!--解决build后,mapper.xml没有加载到targger的-->
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
    </resources>

  </build>
</project>

温馨提示:build中需要添加resources相关代码,否则项目编译后,mapper相关的xml不会保存到target中,导入操作mybatis失败。

3.2 web.xml添加相关配置

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
    <display-name></display-name>


    <!-- 解决post请求中文乱码 -->
    <filter>
        <filter-name>characterencodingfilter</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>characterencodingfilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>



    <!--
    (1)dispatcherservlet是前端控制器设计模式的实现,提供spring web mvc的集中访问点,
    而且负责职责的分派,而且与spring ioc容器无缝集成
    (2)load-on-startup:表示启动容器时初始化该servlet;
    (3)url-pattern:表示哪些请求交给spring web mvc处理, “/” 是用来定义默认servlet映射的。
    也可以如“*.html”表示拦截所有以html为扩展名的请求。
    -->
    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class>
        <init-param>
            <!-- 如果不配置contextconfiglocation,则默认加载web-info下面的applicationcontext.xml -->
            <param-name>contextconfiglocation</param-name>
            <param-value>classpath:spring/applicationcontext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--
    配置方式有几种
    1. *.action,可以访问以.action结尾,由dispatcherservlet进行解析
    2. /,所有访问的地址由dispatcherservlet进行解析,对于静态文件的解析需要配置不让dispatcherservlet进行解析
    3. /*,这样配置不对,使用这种配置,最终要转发到一个jsp页面,仍然由dispatcherservlet解析jsp,不能根据jsp找到handler,结果错误
 -->
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

温馨提示:
我们可能会在其他的项目中看到ssm(spring、spring mvc、mybatis)的配置文件都在同一个xml文件中,但是这样不好管理,在该文章中,我们的spring文件夹中的配置文件采用解耦方式进行配置,在web.xml中进行总的配置加载,再分别加载持久层、应用层、逻辑层,正常配置后的文件结构如下:

 
Java之mybatis详解

3.3 resources中添加logback.xml配置日志文件

<!-- ch.qos.logback.classic.filter.thresholdfilter  临界值过滤器, 过滤掉低于指定临界值的日志
ch.qos.logback.classic.filter.levelfilter   将过滤器的日志级别配置为info,所有info级别的日志交给appender处理,非info级别的日志,被过滤掉。 -->
<configuration>
    <property name="app_name" value="ssm_demo" /> //这里为此项目的日志文件夹名
    <property name="log.dir" value="f:/home"></property> //这里为日志的存储地址
    <timestamp key="bysecond" datepattern="yyyymmdd hhmmss"/>
    <contextname>${app_name}</contextname>
 
    <appender name="stdout" class="ch.qos.logback.core.consoleappender">
        <layout class="ch.qos.logback.classic.patternlayout">
            <pattern>%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{85} [%file:%line] - %msg%n</pattern>
        </layout>
    </appender>
 
    <!-- 按日期和大小区分的滚动日志 -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.rollingfileappender">
        <encoder>
            <pattern>%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{85} - %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.levelfilter">
            <level>info</level>
            <onmatch>accept</onmatch>
            <onmismatch>deny</onmismatch>
        </filter>
        <rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy">
            <filenamepattern>${log.dir}/${app_name}/info/info.%d{yyyy-mm-dd}-%i.log</filenamepattern>
            <maxhistory>30</maxhistory>
 
            <timebasedfilenamingandtriggeringpolicy
                    class="ch.qos.logback.core.rolling.sizeandtimebasedfnatp">
                <maxfilesize>10mb</maxfilesize>
            </timebasedfilenamingandtriggeringpolicy>
        </rollingpolicy>
    </appender>
 
 
    <!-- 按日期和大小区分的滚动日志 -->
    <appender name="file_debug" class="ch.qos.logback.core.rolling.rollingfileappender">
        <!-- 必须指定,否则不会往文件输出内容 -->
        <encoder>
            <pattern>%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{85} - %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.levelfilter">
            <level>debug</level>
            <onmatch>accept</onmatch>
            <onmismatch>deny</onmismatch>
        </filter>
 
        <!-- 必需要指定rollingpolicy 与 triggeringpolicy 属性   否则不会生成文件-->
        <rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy">
            <filenamepattern>${log.dir}/${app_name}/debug/debug.%d{yyyy-mm-dd}-%i.log</filenamepattern>
            <maxhistory>30</maxhistory>
 
            <timebasedfilenamingandtriggeringpolicy
                    class="ch.qos.logback.core.rolling.sizeandtimebasedfnatp">
                <maxfilesize>10mb</maxfilesize>
            </timebasedfilenamingandtriggeringpolicy>
 
        </rollingpolicy>
    </appender>
 
 
    <!-- error级别只按日期滚动生成日志 -->
    <appender name="file_error" class="ch.qos.logback.core.rolling.rollingfileappender">
        <!-- 必须指定,否则不会往文件输出内容 -->
        <encoder>
            <pattern>%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{85} - %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.thresholdfilter">
            <level>error</level>
            <!--    <onmatch>accept</onmatch>
                <onmismatch>deny</onmismatch>-->
        </filter>
 
        <!-- 必需要指定rollingpolicy 与 triggeringpolicy 属性   否则不会生成文件-->
        <rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy">
            <filenamepattern>${log.dir}/${app_name}/error/error.%d{yyyy-mm-dd}-%i.log</filenamepattern>
            <maxhistory>30</maxhistory>
            <timebasedfilenamingandtriggeringpolicy class="ch.qos.logback.core.rolling.sizeandtimebasedfnatp">
                <maxfilesize>10mb</maxfilesize>
            </timebasedfilenamingandtriggeringpolicy>
        </rollingpolicy>
        <!-- 默认值是10mb。 -->
        <!--     <triggeringpolicy class="ch.qos.logback.core.rolling.sizebasedtriggeringpolicy">
                  <maxfilesize>5mb</maxfilesize>
            </triggeringpolicy>  -->
    </appender>
 
    <!-- 滚动记录文件 -->
    <appender name="monitor" class="ch.qos.logback.core.rolling.rollingfileappender">
        <encoder>
            <pattern>%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{85} - %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.thresholdfilter">
            <level>debug</level>
        </filter>
        <rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy">
            <filenamepattern>${log.dir}/${app_name}/monitor/monitor.%d{yyyy-mm-dd}-%i.log</filenamepattern>
            <maxhistory>30</maxhistory>
            <timebasedfilenamingandtriggeringpolicy
                    class="ch.qos.logback.core.rolling.sizeandtimebasedfnatp">
                <maxfilesize>10mb</maxfilesize>
            </timebasedfilenamingandtriggeringpolicy>
        </rollingpolicy>
    </appender>
 
    <logger name="org" level="info" />  <!--将org包下面的所有日志级别设为了error -->
    <logger name="monitor" additivity="false" level="debug" />
 
    <logger name="monitor" additivity="false" level="debug">
        <appender-ref ref="monitor" />
    </logger>
 
    <root level="debug">
        <appender-ref ref="stdout" />
        <appender-ref ref="file_info" />
        <appender-ref ref="file_debug" /> //上线时 这个需注释掉,debug级别的日志
        <appender-ref ref="file_error" />
    </root>
</configuration>

3.4 resources中新建properties文件夹,并添加db.properties文件

jdbc.driver=com.mysql.jdbc.driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=147258qq

新建后项目结构如下:

 
Java之mybatis详解

3.5 resources文件夹中新建spring文件夹,并创建相关依赖文件
新建applicationcontext.xml

<?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"
    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">
    
    <!-- 这样classpath:properties目录下的.properties文件就会被spring加载 -->
    <context:property-placeholder location="classpath:properties/*.properties"/>
    
    <!--
        对于spring配置文件的编写,我想,对于经历过庞大项目的人,都有那种恐惧的心理,太多的配置文件。
        不过,分模块都是大多数人能想到的方法,但是,怎么分模块,那就是仁者见仁,智者见智了。我的策略是使用import。 
        下面的配置, 再resources/spring目录下的以applicationcontext开头的xml文件将全部被加载
     -->
    <import resource="applicationcontext-*.xml"/>
</beans>

新建applicationcontext-dao.xml

<?xml version="1.0" encoding="utf-8" ?>
<!doctype configuration
        public "-//mybatis.org//dtd config 3.0//en"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!-- 加载属性文件 这个位置无需加载,因为在-->
    <properties resource="properties/db.properties">
        <!--properties中还可以配置一些属性名和属性值  -->
        <!-- <property name="jdbc.driver" value=""/> -->
   </properties>

    <!-- 全局配置参数,需要时再设置 -->
    <settings>
        <!-- 打开延迟加载 的开关 -->
        <setting name="lazyloadingenabled" value="true"/>
        <!-- 将积极加载改为消极加载即按需要加载 -->
        <setting name="aggressivelazyloading" value="false"/>
        <!-- 开启二级缓存 -->
        <setting name="cacheenabled" value="true"/>
    </settings>

    <!-- 别名定义 -->
    <typealiases>

        <!-- 针对单个别名定义
        type:类型的路径
        alias:别名
         -->
        <!-- <typealias type="cn.itcast.mybatis.po.user" alias="user"/> -->
        <!-- 批量别名定义
        指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
        -->
        <package name="com.wxc.vo"/>

    </typealiases>

    <!-- 和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理,事务控制由mybatis-->
            <transactionmanager type="jdbc" />
            <!-- 数据库连接池,由mybatis管理-->
            <datasource type="pooled">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </datasource>
        </environment>
    </environments>

    <!-- 加载 映射文件 -->
    <mappers>
        <!--通过resource方法一次加载一个映射文件 -->
        <!-- <mapper resource="mapper/usermapper.xml"/> -->

        <!-- 通过mapper接口加载单个 映射文件
        遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
        上边规范的前提是:使用的是mapper代理方法
         -->
        <!-- <mapper class="cn.itcast.mybatis.mapper.usermapper"/> -->

        <!-- 批量加载mapper
        指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载
        遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
        上边规范的前提是:使用的是mapper代理方法
         -->
        <package name="com.wxc.mapper"/>

    </mappers>

</configuration>

新建applicationcontext-service.xml

<?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: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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">



    <!-- 自动扫描的包名 -->
    <context:component-scan base-package="com.wxc.service"/>

</beans>

新建applicationcontext-web.xml

<?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: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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    
    <!-- 
        开启注解映射的支持
        开启mvc注解   相当于
        <bean class="org.springframework.web.servlet.mvc.method.annotation.requestmappinghandlermapping"/>
        <bean class="org.springframework.web.servlet.mvc.method.annotation.requestmappinghandleradapter"/>
     -->
    <mvc:annotation-driven/>


    
    <!-- 自动扫描的包名 -->
    <context:component-scan base-package="com.wxc.controller"/>

</beans>

配置完成后项目结构如下:

 
Java之mybatis详解

4. 实现基本的增删改查

4.1 创建在com.wxc.vo包下创建测试的实体类
创建msgvo.java

package com.wxc.vo;

/**
 *  用于将数据返回给前端
 */
public class msgvo {

    private string code;

    private string msg;

    public msgvo(string code, string msg) {
        this.code = code;
        this.msg = msg;
    }

    public msgvo() {
    }

    public string getcode() {
        return code;
    }

    public string getmsg() {
        return msg;
    }

    public void setcode(string code) {
        this.code = code;
    }

    public void setmsg(string msg) {
        this.msg = msg;
    }
}

创建user.java

package com.wxc.vo;

public class user {

    private int id;

    private string name;

    private string sex;

    public user() {
    }

    public user(int id, string name, string sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
    }

    public void setid(int id) {
        this.id = id;
    }

    public void setname(string name) {
        this.name = name;
    }

    public void setsex(string sex) {
        this.sex = sex;
    }

    public int getid() {
        return id;
    }

    public string getname() {
        return name;
    }

    public string getsex() {
        return sex;
    }

    @override
    public string tostring() {
        return "user{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}


4.2 com.wxc.service包下创建testmybatisservice.java用于操作数据库的业务处理

package com.wxc.service;

import com.wxc.vo.user;
import com.wxc.vo.user_;
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 org.springframework.stereotype.service;

import java.io.ioexception;
import java.io.inputstream;
import java.util.list;

/**
 * 测试mybatis的基本使用
 */
@service(value = "/testmybatisservice")
public class testmybatisservice {

    // 需要向dao实现类中注入sqlsessionfactory
    // 这里通过构造方法注入
    private sqlsessionfactory sqlsessionfactory;

    //初始化sqlsessionfactory
    private void initsqlsessionfactory() throws ioexception {

        // mybatis配置文件
        string resource = "spring/applicationcontext-dao.xml";

        // 得到配置文件流
        inputstream inputstream = resources.getresourceasstream(resource);

        // 创建会话工厂,传入mybatis的配置文件信息
        sqlsessionfactory = new sqlsessionfactorybuilder()
                .build(inputstream);
    }


    /**
     * 新增用户
     * @param user
     * @return
     */
    public int insertuser(user user) throws ioexception {

        initsqlsessionfactory();

        sqlsession sqlsession = sqlsessionfactory.opensession();

        system.out.println(user.tostring());

        //执行插入操作
        int n = sqlsession.insert("com.wxc.mapper.usermapper.insertuser", user);

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

        // 释放资源
        sqlsession.close();

        return n;
    }

    /**
     * 删除用户
     * @param id
     * @return
     */
    public int deleteuser(int id) throws ioexception {

        initsqlsessionfactory();

        sqlsession sqlsession = sqlsessionfactory.opensession();

        //执行插入操作
        int n = sqlsession.delete("com.wxc.mapper.usermapper.deleteuser", id);

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

        // 释放资源
        sqlsession.close();

        return n;
    }

    /**
     * 修改用户
     * @param user
     * @return
     */
    public int updateuser(user user) throws ioexception {

        initsqlsessionfactory();

        sqlsession sqlsession = sqlsessionfactory.opensession();

        //执行插入操作
        int n = sqlsession.update("com.wxc.mapper.usermapper.updateuser", user);

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

        // 释放资源
        sqlsession.close();

        return n;
    }

    /**
     * 查询用户
     * @return
     */
    public user selectuser() throws ioexception {

        initsqlsessionfactory();

        sqlsession sqlsession = sqlsessionfactory.opensession();

        //执行插入操作
        user user = sqlsession.selectone("com.wxc.mapper.usermapper.selectuser");

        // 释放资源
        sqlsession.close();

        return user;
    }

    /**
     * 查询用户  测试resultmap使用
     * @return
     */
    public list<user_> selectuser_() throws ioexception {

        initsqlsessionfactory();

        sqlsession sqlsession = sqlsessionfactory.opensession();

        //执行插入操作
        list<user_> user = sqlsession.selectlist("com.wxc.mapper.usermapper.selectuser_");

        // 释放资源
        sqlsession.close();

        return user;
    }
}

4.3 在com.wxc.mapper包中创建相应sql操作
创建usermapper.java

package com.wxc.mapper;

import com.wxc.vo.user;
import com.wxc.vo.user_;

import java.util.list;

/**
 * description: mapper接口,相当 于dao接口,用户管理
 */
public interface usermapper {
    
    //插入用户
    public int insertuser(user user);
    
    //删除用户
    public int deleteuser(int id);

    //查询用户
    public user selecttuser();

    //修改用户
    public int updateuser(user user);
}

创建usermapper.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命名空间,作用就是对sql进行分类化管理,理解sql隔离 
注意:使用mapper代理方法开发,namespace有特殊重要的作用,namespace等于mapper接口地址
-->
<mapper namespace="com.wxc.mapper.usermapper">

    <!-- 添加用户 
    parametertype:指定输入 参数类型是pojo(包括 用户信息)
    #{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过ognl获取对象的属性值
    -->
    <insert id="insertuser" parametertype="user">
          insert into user(id, name) values(#{id}, #{name})
    </insert>
    
    <!-- 删除 用户
    根据id删除用户,需要输入 id值
     -->
    <delete id="deleteuser" parametertype="java.lang.integer">
        delete from user where id=#{id}
    </delete>
    
    <!-- 根据id更新用户
    分析:
    需要传入用户的id
    需要传入用户的更新信息
    parametertype指定user对象,包括 id和更新信息,注意:id必须存在
    #{id}:从输入 user对象中获取id属性值
     -->
    <update id="updateuser" parametertype="user">
        update user set name=#{name} where id=#{id}
    </update>

    <select id="selectuser" resulttype="user">
        select id, name from user  where id = 1
    </select>

com.wxc.controller中创建testmybatiscontroller.java用于测试访问

package com.wxc.controller;

import com.wxc.service.testmybatisservice;
import com.wxc.vo.msgvo;
import com.wxc.vo.user;
import com.wxc.vo.user_;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.controller;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.responsebody;

import java.io.ioexception;
import java.util.list;

/**
 * 测试mybatis的基本使用
 */
@controller
@requestmapping(value = "/testmybatiscontroller")
public class testmybatiscontroller {

    @autowired
    private testmybatisservice testmybatisservice;

    /**
     * 新增用户
     * @return
     */
    @requestmapping(value = "/insertuser")
    @responsebody
    public msgvo insertuser(user user) throws ioexception {

        system.out.println(user.tostring());

        int n = testmybatisservice.insertuser(user);

        msgvo vo = new msgvo(n+"", "成功");

        return vo;
    }

    /**
     * 删除用户
     * @return
     */
    @requestmapping(value = "/deleteuser")
    @responsebody
    public msgvo deleteuser(int id) throws ioexception {

        system.out.println(id+"");

        int n = testmybatisservice.deleteuser(id);

        msgvo vo = new msgvo(n+"", "成功");

        return vo;
    }


    /**
     * 修改用户
     * @return
     */
    @requestmapping(value = "/updateuser")
    @responsebody
    public msgvo updateuser(user user) throws ioexception {

        int n = testmybatisservice.updateuser(user);

        msgvo vo = new msgvo(n+"", "成功");

        return vo;
    }

    /**
     * 查询用户
     * @return
     */
    @requestmapping(value = "/selectuser")
    @responsebody
    public user selectuser() throws ioexception {

        user user = testmybatisservice.selectuser();

        return user;
    }


4.4 运行项目后访问结果如下:

调用新增用户接口

 
Java之mybatis详解
 
Java之mybatis详解

5. 输入与输出映射

5.1 输入与输出介绍
(1)resulttype:使用resulttype进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
(2)resultmap:如果查询出来的列名和pojo的属性名不一致,通过定义一个resultmap对列名和pojo属性名之间作一个映射关系

5.2 resultmap代码演示
com.wxc.vo中新建实体类user_.java

package com.wxc.vo;

public class user_ {

    private int id_;

    private string name_;

    private string sex_;

    public user_(int id_, string name_, string sex_) {
        this.id_ = id_;
        this.name_ = name_;
        this.sex_ = sex_;
    }

    public user_() {
    }

    public void setid_(int id_) {
        this.id_ = id_;
    }

    public void setname_(string name_) {
        this.name_ = name_;
    }

    public void setsex_(string sex_) {
        this.sex_ = sex_;
    }

    public int getid_() {
        return id_;
    }

    public string getname_() {
        return name_;
    }

    public string getsex_() {
        return sex_;
    }
}


com.wxc.mapper的usermapper.java中新增以下方法

//查询用户
public list<user_> selecttuser_();

com.wxc.mapper的usermapper.xml中新增以下代码

<!-- 定义resultmap
将select id id_,name name_, sex, sex_ from user 和user类中的属性作一个映射关系

type:resultmap最终映射的java对象类型,可以使用别名
id:对resultmap的唯一标识
 -->
    <resultmap type="user_" id="userresultmap">
        <!-- id表示查询结果集中唯一标识
        column:查询出来的列名
        property:type指定的pojo类型中的属性名
        最终resultmap对column和property作一个映射关系 (对应关系)
        -->
        <id column="id" property="id_"/>
        <!--
        result:对普通名映射定义
        column:查询出来的列名
        property:type指定的pojo类型中的属性名
        最终resultmap对column和property作一个映射关系 (对应关系)
         -->
        <result column="name" property="name_"/>
        <result column="sex" property="sex_"/>

    </resultmap>

    <!--测试resultmap使用-->
    <select id="selectuser_" resultmap="userresultmap">
        select id , name , sex  from user
    </select>

com.wxc.service的testmybatisservice.java添加以下方法:

    /**
     * 查询用户  测试resultmap使用
     * @return
     */
    public list<user_> selectuser_() throws ioexception {

        initsqlsessionfactory();

        sqlsession sqlsession = sqlsessionfactory.opensession();

        //执行插入操作
        list<user_> user = sqlsession.selectlist("com.wxc.mapper.usermapper.selectuser_");

        // 释放资源
        sqlsession.close();

        return user;
    }

com.wxc.controller的testmybatiscontroller.java添加以下方法

  /**
     * 查询用户  测试resultmap使用
     * @return
     */
    @requestmapping(value = "/selectuser_")
    @responsebody
    public list<user_> selectuser_() throws ioexception {

        list<user_> user_ = testmybatisservice.selectuser_();

        return user_;
    }

运行项目后访问情况如下:

 
Java之mybatis详解

6. 动态sql实现

6.1 什么是动态sql
  mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装。
6.2 动态sql实现方式
(1)if-else
(2)sql片段
(3)foreach

6.3 代码演示(包含if-else、sql片段、foreach)
com.wxc.vo中新建实体类user2.java

package com.wxc.vo;

import java.util.list;

public class user2 extends  user {

    private list<integer> ids;

    public user2(list<integer> ids) {
        this.ids = ids;
    }

    public user2(int id, string name, string sex, list<integer> ids) {
        super(id, name, sex);
        this.ids = ids;
    }

    public user2()
    {

    }

    public list<integer> getids() {
        return ids;
    }

    public void setids(list<integer> ids) {
        this.ids = ids;
    }

    @override
    public string tostring() {
        return "user2{" +
                "ids=" + ids +
                '}';
    }
}

com.wxc.mapper包下新建seniorusermapper.java

package com.wxc.mapper;

import com.wxc.vo.user;
import com.wxc.vo.user2;

import java.util.list;

/**
 * 测试高级的
 */
public interface seniorusermapper {

    //查询用户
    public list<user> selectuser(user user);

    //修改用户
    public int updateuser(user2 user2);
}

com.wxc.mapper包下新建seniorusermapper.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命名空间,作用就是对sql进行分类化管理,理解sql隔离 
注意:使用mapper代理方法开发,namespace有特殊重要的作用,namespace等于mapper接口地址
-->
<mapper namespace="com.wxc.mapper.seniorusermapper">


    <sql id="verification">
        <!--if中检验的是传送进来的参数-->
        <if test="sex != null and name != null">
            sex = #{sex}
        </if>
    </sql>

    <select id="selectuser" parametertype="user" resulttype="user">
        select id, name,sex from user
        <!--where会自动去掉条件中的第一个and-->
        <where>
            <!--if中检验的是传送进来的参数-->
            <!--<if test="sex != null and name != null">
                sex = #{sex}
            </if>-->

            <!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前边加namespace,该效果与上面的if等同 -->
            <include refid="verification"></include>
            <!--这里可以添加其他条件-->
        </where>
    </select>


    <update id="updateuser" parametertype="user2">
        update user set name=#{name} where
        <foreach collection="ids" item="id" open="id in(" close=")" separator=",">
            id = #{id}
        </foreach>
    </update>



</mapper>

com.wxc.service包下新建testseniormybatisservice.java

 package com.wxc.service;

import com.wxc.vo.user;
import com.wxc.vo.user2;
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 org.springframework.stereotype.service;

import java.io.ioexception;
import java.io.inputstream;
import java.util.list;

/**
 * 测试mybatis高级使用
 */
@service(value = "/testseniormybatisservice")
public class testseniormybatisservice {

    // 需要向dao实现类中注入sqlsessionfactory
    // 这里通过构造方法注入
    private sqlsessionfactory sqlsessionfactory;

    //初始化sqlsessionfactory
    private void initsqlsessionfactory() throws ioexception {

        // mybatis配置文件
        string resource = "spring/applicationcontext-dao.xml";

        // 得到配置文件流
        inputstream inputstream = resources.getresourceasstream(resource);

        // 创建会话工厂,传入mybatis的配置文件信息
        sqlsessionfactory = new sqlsessionfactorybuilder()
                .build(inputstream);
    }

    /**
     * 查询用户
     * @return
     */
    public list<user> selectuser(user user) throws ioexception {

        initsqlsessionfactory();

        sqlsession sqlsession = sqlsessionfactory.opensession();

        system.out.println("sex的值为:"+user);

        //执行插入操作
        list<user> user2 = sqlsession.selectlist("com.wxc.mapper.seniorusermapper.selectuser", user);

        // 释放资源
        sqlsession.close();

        return user2;
    }

    /**
     * 批量修改用户
     * @return
     */
    public int updateuser(user2 user) throws ioexception {

        initsqlsessionfactory();

        sqlsession sqlsession = sqlsessionfactory.opensession();

        system.out.println("sex的值为:"+user);

        //执行插入操作
        int n  = sqlsession.update("com.wxc.mapper.seniorusermapper.updateuser", user);

        // 释放资源
        sqlsession.close();

        return n;
    }
}

com.wxc.controller包下新建testseniormybatiscontroller.java

package com.wxc.controller;

import com.wxc.service.testseniormybatisservice;
import com.wxc.vo.user;
import com.wxc.vo.user2;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.controller;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.responsebody;

import java.io.ioexception;
import java.util.list;

/**
 * 测试mybatis高级使用
 */
@controller
@requestmapping(value = "/testseniormybatiscontroller")
public class testseniormybatiscontroller {

    @autowired
    private testseniormybatisservice testseniormybatisservice;

    /**
     * 查询用户
     * @return
     */
    @requestmapping(value = "/selectuser")
    @responsebody
    public string selectuser(user user) throws ioexception {

        list<user> user2 = testseniormybatisservice.selectuser(user);

        return user2.tostring();
    }

    @requestmapping(value = "/updateuser")
    @responsebody
    public string updateuser(user2 user2) throws ioexception {

        int n = testseniormybatisservice.updateuser(user2);

        return n+"";
    }
}

7. 查询缓存

7.1 什么是查询缓存
  mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits提供一级缓存,和二级缓存。

 
Java之mybatis详解

  一级缓存是sqlsession级别的缓存。在操作数据库时需要构造 sqlsession对象,在对象中有一个数据结构(hashmap)用于存储缓存数据。不同的sqlsession之间的缓存数据区域(hashmap)是互相不影响的。
  二级缓存是mapper级别的缓存,多个sqlsession去操作同一个mapper的sql语句,多个sqlsession可以共用二级缓存,二级缓存是跨sqlsession的。
  为什么要用缓存?
  如果缓存中有数据就不用从数据库中获取,大大提高系统性能。

7.2 一级缓存
一级缓存工作原理

 
Java之mybatis详解

第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。

如果sqlsession去执行commit操作(执行插入、更新、删除),清空sqlsession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

7.3 二级缓存
二级缓存工作原理

 
Java之mybatis详解

首先开启mybatis的二级缓存。

sqlsession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

如果sqlsession3去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据。

sqlsession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlsession可以共享一个usermapper的二级缓存区域。
usermapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。
每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。

7.4 开启二级缓存
mybaits的二级缓存是mapper范围级别,除了在sqlmapconfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。

在核心配置文件sqlmapconfig.xml中加入

<setting name="cacheenabled" value="true"/>
 
Java之mybatis详解

8. mybatis与hibernate区别

hibernate
  hibernate是一个标准orm框架(对象关系映射)。入门门槛较高的,不需要程序写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难的。
  应用场景:
  适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。。

mybatis
  mybatis专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的orm框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。
  应用场景:
  适用与需求变化较多的项目,比如:互联网项目。
  企业进行技术选型,以低成本 高回报作为技术选型的原则,根据项目组的技术力量进行选择。

三、项目源码下载

链接:https://pan.baidu.com/s/1lihtfqq_i3msvinga-mcdg
提取码:qmja

四、参考文章

http://yun.itheima.com/course/289.html