1. 工程結構
![工程結構 工程結構](http://static.javashuo.com/static/loading.gif)
2. pom依賴
<?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.2.RELEASE</version>
<relativePath/> <!-- JDK>=1.8 -->
</parent>
<groupId>com.example</groupId>
<artifactId>mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. yml配置
# DataSource Config
spring:
datasource:
driver-class-name: org.h2.Driver
# spring提供的功能,用來初始化數據庫
schema: classpath:db/schema-h2.sql
# spring提供的功能,用來初始化數據庫
data: classpath:db/data-h2.sql
url: jdbc:h2:mem:test
username: root
password: test
# mybatis配置
mybatis:
# 聲明實體別名
type-aliases-package: com.example.mybatis.domain
# mapper xml 掃描範圍
mapper-locations: classpath:mapper/*.xml
4. 啓動類
package com.example.mybatis;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
//限定mapper掃描的範圍,默認值和@SpringBootApplication範圍相同
@MapperScan("com.example.mybatis.mapper")
//開啓mybatis事務
@EnableTransactionManagement
public class MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisApplication.class, args);
}
}
5. 實體類(模型層)
package com.example.mybatis.domain;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
6. 映射類(持久層)
package com.example.mybatis.mapper;
import com.example.mybatis.domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.jdbc.SQL;
import java.util.List;
//聲明這是一個mapper
@Mapper
//mapper中,註解和XML能夠同時存在
//但通常地,使用XML就不要使用註解,避免混淆,
//普通註解和動態SQL註解(Provider)混用較爲常見,
//複雜sql動態生成,簡單sql直接寫在註解中
public interface UserMapper {
//使用註解定義SQL語句
@Select("select * from user")
List<User> selectUserList();
@Select("select * from user where id=#{id}")
User findUserById(@Param("id") Long id);
//使用動態生成的sql
@SelectProvider(type = UserMapperProvider.class, method = "findByAge")
List<User> findUserByAge(Integer age);
@SelectProvider(type = UserMapperProvider.class, method = "findByName")
List<User> findUserByName(String name);
//使用XML定義的SQL
int deleteByPrimaryKey(Long id);
int insert(User record);
int insertSelective(User record);
User selectByPrimaryKey(Long id);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
//動態SQL類,通常單獨寫在某處,寫在這裏只爲方便
class UserMapperProvider{
public String findByAge(Integer age){
return "SELECT id, name, age, email FROM user WHERE age = ".concat(String.valueOf(age));
}
public String findByName(String name){
//使用mybatis提供的工具類來準備相同的 SQL 語句
return new SQL(){
{
SELECT("id, name, age, email");
FROM("user");
WHERE("name = '".concat(name).concat("'"));
}
}.toString();
}
}
}
7. 映射配置(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" >
<!-- 設定命名空間,通常約定爲包名,可簡化配置 -->
<mapper namespace="com.example.mybatis.mapper.UserMapper" >
<resultMap id="BaseResultMap" type="User" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="INTEGER" />
<result column="email" property="email" jdbcType="VARCHAR" />
</resultMap>
<!-- sql片斷 -->
<sql id="Base_Column_List" >
id, name, age, email
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="long" >
select
<include refid="Base_Column_List" />
from user
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="long" >
delete from user
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="User" >
insert into user (id, name, age,
email)
values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER},
#{email,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="User" >
insert into user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="name != null" >
name,
</if>
<if test="age != null" >
age,
</if>
<if test="email != null" >
email,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="name != null" >
#{name,jdbcType=VARCHAR},
</if>
<if test="age != null" >
#{age,jdbcType=INTEGER},
</if>
<if test="email != null" >
#{email,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="User" >
update user
<set >
<if test="name != null" >
name = #{name,jdbcType=VARCHAR},
</if>
<if test="age != null" >
age = #{age,jdbcType=INTEGER},
</if>
<if test="email != null" >
email = #{email,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="User" >
update user
set name = #{name,jdbcType=VARCHAR},
age = #{age,jdbcType=INTEGER}
email = #{email,jdbcType=VARCHAR},
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
8. service類
package com.example.mybatis.service;
import com.example.mybatis.domain.User;
import com.example.mybatis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
//使用事物,能夠在web層,也可在service層
@Transactional
public void addUsers(){
User user1 = new User();
user1.setId(6L);
user1.setAge(12);
user1.setName("shier");
user1.setEmail("shier@demo.com");
User user2 = new User();
user2.setId(7L);
user2.setAge(1234);
user2.setName("dalao");
user2.setEmail("dalao@demo.com");
userMapper.insert(user1);
userMapper.insert(user2);
String err = null;
System.out.println("事物回滾,addUsers()將一個用戶也不能添加");
err.indexOf('e');
}
}
@Transational具體的參數及解釋
屬性 |
類型 |
描述 |
value |
String |
可選的限定描述符,指定使用的事務管理器 |
propagation |
enum: Propagation |
可選的事務傳播行爲設置 |
isolation |
enum: Isolation |
可選的事務隔離級別設置 |
readOnly |
boolean |
讀寫或只讀事務,默認讀寫 |
timeout |
int (in seconds granularity) |
事務超時時間設置 |
rollbackFor |
Class對象數組,必須繼承自Throwable |
致使事務回滾的異常類數組 |
rollbackForClassName |
類名數組,必須繼承自Throwable |
致使事務回滾的異常類名字數組 |
noRollbackFor |
Class對象數組,必須繼承自Throwable |
不會致使事務回滾的異常類數組 |
noRollbackForClassName |
類名數組,必須繼承自Throwable |
不會致使事務回滾的異常類名字數組 |
9. 數據庫初始化配置
9.1 schema-h2.sql
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主鍵ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年齡',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '郵箱',
PRIMARY KEY (id)
);
9.2 data-h2.sql
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@demo.com'),
(2, 'Jack', 20, 'test2@demo.com'),
(3, 'Tom', 28, 'test3@demo.com'),
(4, 'Sandy', 21, 'test4@demo.com'),
(5, 'Billie', 24, 'test5@demo.com');
10. 測試類
package com.example.mybatis;
import com.example.mybatis.domain.User;
import com.example.mybatis.mapper.UserMapper;
import com.example.mybatis.service.UserService;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisApplicationTests {
@Autowired
UserMapper userMapper;
@Autowired
UserService userService;
@Test(expected = NullPointerException.class)
public void contextLoads() {
//使用XML定義的SQL
User user1 = userMapper.selectByPrimaryKey(1L);
//使用註解定義的SQL
User user2 = userMapper.findUserById(2L);
//使用註解定義的動態SQL
List<User> user3 = userMapper.findUserByAge(21);
System.out.println("XML定義的按主鍵查詢用戶\n"+user1);
System.out.println("annotation定義的按ID查詢用戶\n"+user2);
System.out.println("annotation定義的按年齡查詢用戶\n"+user3);
System.out.println("---------事物---------");
userService.addUsers();
}
@After
public void after(){
System.out.println("--------查詢全部用戶---------");
//註解定義的SQL能自動轉換類型爲實體類型
List<User> users = userMapper.selectUserList();
users.forEach(System.out::println);
}
}
11. 控制檯輸出
XML定義的按主鍵查詢用戶
User(id=1, name=Jone, age=18, email=test1@demo.com)
annotation定義的按ID查詢用戶
User(id=2, name=Jack, age=20, email=test2@demo.com)
annotation定義的按年齡查詢用戶
[User(id=4, name=Sandy, age=21, email=test4@demo.com)]
---------事物---------
事物回滾,addUsers()將一個用戶也不能添加
--------查詢全部用戶---------
User(id=1, name=Jone, age=18, email=test1@demo.com)
User(id=2, name=Jack, age=20, email=test2@demo.com)
User(id=3, name=Tom, age=28, email=test3@demo.com)
User(id=4, name=Sandy, age=21, email=test4@demo.com)
User(id=5, name=Billie, age=24, email=test5@demo.com)