- springboot整合mybaties demo地址:https://github.com/ningL32/springboot-mybaties
- mybaties增删改查、批量
- mybaties面试
- 一 、springboot整合mybaties
新建工程,https://start.spring.io/ 新建工程,生成项目基础文件,使用idea导入
pom.xml文件如下
<?xml version="1.0" encoding="UTF-8"?>
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ningl</groupId>
<artifactId>mybaties</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybaties</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!--druid-->
<!--<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.18</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 配置我们的application.yml 文件,注意文件目录 和 项目名
server:
tomcat:
uri-encoding: UTF-8
max-threads: 1000
min-spare-threads: 30
port: 8083
servlet:
context-path: /mybaties
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/testshiro?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
resources:
static-locations: classpath:/static/,classpath:/templates/view/
thymeleaf:
suffix: .html
prefix: classpath:/templates/view/
mode: HTML5
encoding: UTF-8
cache: false
- 配置完成之后,在templates路径下新建view文件夹,用来存放我们的.html文件,新建一个index.html,新建一个controller 层,在该包下新建ViewController类,测试是否集成了web模块。
index.html如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
访问页面成功,hello java!
</body>
</html>
控制层代码如下:
package com.ningl.mybaties.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
/**
*@program: mybaties
*@description: 页面跳转
*@author: ningl
*@create: 2019.2.26-0.0
*/
@Controller
public class ViewController {
@GetMapping("/index.html")
public ModelAndView index(ModelAndView mv){
mv.setViewName("index.html");
return mv;
}
}
- 在浏览器输入localhost:8083/mybaties/index.html
- 添加mybaties的依赖更改application.yml文件,正式集成mybaties,
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
在application.xml添加mybaties的配置 mybatis: 和spring:平级
mybatis:
mapper-locations: classpath:mappers/*Mapper.xml
type-aliases-package: com.ningl.mybaties.dao
- 新建一些测试类。例如成语类
CREATE TABLE `play_idiom` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`idiom` varchar(255) NOT NULL COMMENT '成语',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;
对应的实体类如下:
package com.ningl.mybaties.entity;
import lombok.Data;
/**
*@program: mybaties
*@description: 成语库 实体类
*@author: ningl
*@create: 2019.2.26-0.00
*/
public @Data class PlayIdiom {
/**
* id
*/
private Integer id;
/**
* 成语
*/
private String idiom;
}
- 新建service,serviceImpl,dao,注意在serviceImpl上添加注解@Service,在dao层添加注解@Mapper:mybatis 根据接口定义与Mapper文件中的sql语句动态创建接口实现。具体如下:
service包下的IdiomService 接口:
package com.ningl.mybaties.service;
import com.ningl.mybaties.entity.PlayIdiom;
import java.util.List;
/**
*@program: mybaties
*@description: 成语接口
*@author: ningl
*@create: 2019.2.26-0.00
*/
public interface IdiomService {
List<PlayIdiom> findIdioms();
boolean addIdom(String idiom);
boolean delteIdioms(String ids);
}
service.impl包下的IdiomServiceImpl 实现类:
package com.ningl.mybaties.service.impl;
import com.ningl.mybaties.dao.IdiomDao;
import com.ningl.mybaties.entity.PlayIdiom;
import com.ningl.mybaties.service.IdiomService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
*@program: mybaties
*@description: 成语实现层
*@author: ningl
*@create: 2019.2.26-0.00
*/
@Transactional(rollbackFor = Exception.class)
@Service
public class IdiomServiceImpl implements IdiomService {
@Resource
private IdiomDao idiomDao;
/**
* 获取所有的成语
* @return
*/
@Override
public List<PlayIdiom> findIdioms() {
return idiomDao.findIdioms();
}
/**
* 新增成语
* @param idiom
* @return
*/
@Override
public boolean addIdom(String idiom) {
int flag = 0;
String rgx = ",";
if(idiom.indexOf(rgx) == -1){
flag = idiomDao.addIdiom(idiom);
}else {
String[] arr = idiom.split(idiom);
for (int i=0;i<arr.length;i++) {
flag = idiomDao.addIdiom(idiom);
}
}
return flag > 0? true:false;
}
/**
* 删除成语
* @param ids
* @return
*/
@Override
public boolean delteIdioms(String ids) {
int flag = 0;
String rgx = ",";
HashMap<String,Object> map = new HashMap<>();
List list = new ArrayList();
if(ids.indexOf(rgx) == -1){
list.add(ids);
}else{
String[] arr = ids.split(rgx);
for (String str:arr) {
list.add(str);
}
}
map.put("ids",list);
return idiomDao.delteIdioms(map) > 0 ? true:false;
}
}
dao 包下的IdiomDao 类;
package com.ningl.mybaties.dao;
import com.ningl.mybaties.entity.PlayIdiom;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.HashMap;
import java.util.List;
/**@Author ningl
* @Description IdiomDao 类
* @Date 2019/2/26 20:44
**/
@Mapper
public interface IdiomDao {
List<PlayIdiom> findIdioms();
int addIdiom(@Param("idiom") String idiom);
int delteIdioms(HashMap<String, Object> map);
}
根目录下的mapper.xml文件:namespace 对应 dao包下接口类
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ningl.mybaties.dao.IdiomDao">
<select id="findIdioms" resultType="map">
select * from play_idiom
</select>
<insert id="addIdiom" parameterType="String" useGeneratedKeys="true"
keyProperty="id">
insert into play_idiom (idiom)
values (#{idiom})
</insert>
<delete id="delteIdioms" parameterType="map">
delete from play_idiom where 1=1 AND id in
<foreach collection="ids" item="id" index="index" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
- 二、mybaties 面试问答
- #{}和${}的区别是什么?
答:首先 ${} Properties文件中的变量占位符,它可以用于标签属性值和sql内部,属于静态文本替换,而 #{}是sql的参数占位符,Mybatis会将sql中的#{}替换为?号,在sql执行前会使用PreparedStatement的参数设置方法,按序给sql的?号占位符设置参数值 - mybaties 都有哪些标签?
答:还有很多其他的标签resultType,select,sql,where,resultMap,include 加上动态sql的9个标签,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。 - 最佳实践中,通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
答:Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个select、insert、update、delete标签,都会被解析为一个MappedStatement对象。Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。 - insert 方法总是返回一个int值 - 这个值代表的是插入的行数。而自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象
- Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
答:不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;毕竟namespace不是必须的,只是最佳实践而已。原因就是namespace+id是作为Map<String, MappedStatement>的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。 - 在mapper中如何传递多个参数?
答:使用map封装参数,传递值的时候使用map的key .
- #{}和${}的区别是什么?