Java之mybatis详解

文章大纲

一、mybatis介绍
二、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框架图解

 

二、mybatis代码实战

1. 创建maven的javaweb项目

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

 

2. 创建数据库表

表名为: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中进行总的配置加载,再分别加载持久层、应用层、逻辑层,正常配置后的文件结构如下:

 

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

新建后项目结构如下:

 

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> 

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

 

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 运行项目后访问结果如下:

调用新增用户接口

 
 

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_; } 

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

 

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提供一级缓存,和二级缓存。

 

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

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

 

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

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

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

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

 

首先开启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"/> 
 

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

猜你喜欢

转载自www.cnblogs.com/WUXIAOCHANG/p/10776236.html
今日推荐