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
Java之mybatis详解的更多相关文章
- Java源码详解系列(十)--全面分析mybatis的使用、源码和代码生成器(总计5篇博客)
简介 Mybatis 是一个持久层框架,它对 JDBC 进行了高级封装,使我们的代码中不会出现任何的 JDBC 代码,另外,它还通过 xml 或注解的方式将 sql 从 DAO/Repository ...
- [原创]mybatis详解说明
mybatis详解 2017-01-05MyBatis之代理开发模式1 mybatis-Dao的代理开发模式 Dao:数据访问对象 原来:定义dao接口,在定义dao的实现类 dao的代理开发模式 只 ...
- mybatis 详解(三)------入门实例(基于注解)
1.创建MySQL数据库:mybatisDemo和表:user 详情参考:mybatis 详解(二)------入门实例(基于XML) 一致 2.建立一个Java工程,并导入相应的jar包,具体目录如 ...
- mybatis 详解------动态SQL
mybatis 详解------动态SQL 目录 1.动态SQL:if 语句 2.动态SQL:if+where 语句 3.动态SQL:if+set 语句 4.动态SQL:choose(when,o ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Java 序列化Serializable详解
Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...
- Java String类详解
Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...
- 最新java数组的详解
java中HashMap详解 http://alex09.iteye.com/blog/539545 总结: 1.就像引用类型的数组一样,当我们把 Java 对象放入数组之时,并不是真正的把 Java ...
- JAVA IO 类库详解
JAVA IO类库详解 一.InputStream类 1.表示字节输入流的所有类的超类,是一个抽象类. 2.类的方法 方法 参数 功能详述 InputStream 构造方法 available 如果用 ...
随机推荐
- FastDfs上传图片
1.1. 上传步骤 1.加载配置文件,配置文件中的内容就是tracker服务的地址. 配置文件内容:tracker_server=192.168.25.133:22122 2.创建一个TrackerC ...
- SpringBoot19 集成SpringSecurity01 -> 环境搭建、SpringSecurity验证
1 环境搭建 1.1 创建一个SpringBoot项目 项目脚手架 -> 点击前往 1.2 创建一个Restful接口 新建一个Controller类即可 package com.example ...
- vue项目在移动端(手机)调试
查了很长一段时间的资料才搞好. 感悟就是:原来那么简单呐. 首要条件:同一局域网下(大致理解为链接相同的wifi) 1:命令行运行 ipconfig 2: 得到ipv4值, 用该值替换localhos ...
- __new__()方法的使用和实例化
Python中__new__()方法的使用和实例化 1 2 new()是在新式类中新出现的方法,它作用在构造方法init()建造实例之前,可以这么理解,在Python 中存在于类里面的构造方法init ...
- Egg Dropping Puzzle问题的分析
首先,基本问题是这样:You are given two eggs, and access to a 100-storey building. The aim is to find out the h ...
- TCP连接和 time_wait、close_waite
TCP连接和 time_wait.close_waite tags:time_wait close_waite RST TCP 引言:前两天朋友公司的服务器垮掉了,最后查出的原因是发现大量的time_ ...
- js基础进阶--图片上传时实现本地预览功能的原理
欢迎访问我的个人博客:http://www.xiaolongwu.cn 前言 最近在项目上加一个图片裁剪上传的功能,用的是cropper插件,注意到选择本地图片后就会有预览效果,这里整理一下这种预览效 ...
- Stack编程队列
题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 首先定义两个栈 Stack<Integer> stack1 = new Stack<I ...
- 对于spring中事务@Transactional注解的理解
现在spring的配置都喜欢用注解,这边就说下@Transactional 一.如何开启@Transactional支持 要使用@Transactional,spring的配置文件applicatio ...
- RabbitMQ入门:认识并安装RabbitMQ(以Windows系统为例)
最近在学习Spring Cloud,其中消息总线Spring Cloud Bus是必不可少的,但是Spring Cloud Bus目前只支持RabbitMQ和kafka,因此学习RabbitMQ势在必 ...