平凡也就兩個字: 懶和惰;
成功也就兩個字: 苦和勤;
優秀也就兩個字: 你和我。
跟著我從0學習JAVA、spring全家桶和linux運維等知識,帶你從懵懂少年走向人生巔峰,迎娶白富美!
關注微信公眾號【 IT特靠譜 】,每天都會分享技術心得~
持久層框架有很多,常見的持久層框架實現有spring-data-jpa、mybatis(mybatis-plus)和hibernate等。本教學將以mybatis持久層框架為例,詳述springboot整合mybatis框架的過程,並最終通過註解和xml兩種方式實現資料增刪改查(CRUD)操作。
mybatis官方檔案中的解釋:MyBatis 是一款優秀的持久層框架,它支援自定義 SQL、儲存過程以及高階對映。MyBatis 免除了幾乎所有的 JDBC 程式碼以及設定引數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或註解來設定和對映原始型別、介面和 Java POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄。
也就是mybatis對資料庫操作做了大量封裝,使得開發者拿來即用,減少開發成本。同時mybatis支援註解和xml兩種對映方式,也提供對原生sql的支援。
建立springboot專案的過程非常簡單,此處省略。下面是已經建好的springboot專案的目錄結構。
專案名稱:mybatis-demo
略!關注微信公眾號:IT特靠譜,回覆"我要mysql安裝教學"免費領取吧~
mysql資料庫連線資訊如下:
url: jdbc:mysql://localhost:3306/test_mybatis?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
username: root
password: root
建立的資料庫表:user_t, 給資料庫表user_t新增唯一索引。索引欄位為:mobile,索引名:udx_user_mobile。建立表的sql指令碼如下:
CREATE TABLE `user_t` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
`mobile` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '使用者手機號',
`user_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '使用者名稱',
`age` tinyint(4) NULL DEFAULT NULL COMMENT '年齡',
`create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
`update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '最後更新時間',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `udx_user_mobile`(`mobile`) USING BTREE COMMENT '使用者手機號唯一索引'
) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
我們先往user_t資料庫表中插入如下4條資料,用於查詢測試!
INSERT INTO `user_t` VALUES (1, '13111111111', '張三', 10, '2020-10-22 15:58:51', '2020-10-22 18:26:31');
INSERT INTO `user_t` VALUES (2, '13555555555', '李四', 20, '2020-10-22 15:58:59', '2020-10-22 18:26:33');
INSERT INTO `user_t` VALUES (3, '13666666666', '王五', 20, '2020-10-22 15:59:15', '2020-10-22 18:26:35');
INSERT INTO `user_t` VALUES (4, '15222222222', '小六', 40, '2020-10-22 17:30:21', '2020-10-22 18:26:39');
專案pom.xml檔案中新增mysql資料庫驅動、資料庫連線池和mybatis相關依賴包。
<!--持久化api依賴包:與資料庫互動,比如Java bean和資料庫表的對應關係-->
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>
<!--mybatis依賴包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!-- mybatis通用Mapper依賴包:提供了基本的增刪改查Mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
<!--mysql資料庫驅動包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!--Druid資料庫連線池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
在application.properties或application.yml組態檔中新增如下設定。
1)設定資料來源
2)指定Mapper.xml資原始檔所在路徑
3)開啟sql紀錄檔
#mysql設定資料來源
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_mybatis?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
username: root
password: root
#指定Mapper.xml所在路徑
mybatis:
mapper-locations: classpath:mapping/*Mapper.xml
type-aliases-package: com.hc.mybatisdemo.entity
#列印sql紀錄檔
logging:
level:
com:
hc:
mybatisdemo:
mapper: debug
//注意這裡需要引入tk.mybatis這個依賴
import tk.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.hc.mybatisdemo.mapper") //掃描的mapper包路徑
public class MybatisDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisDemoApplication.class, args);
}
}
實體類: User.java
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 使用者實體類
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "user_t")
public class User {
/**
* 主鍵id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
/**
* 使用者手機號
*/
@Column(name = "mobile")
private String mobile;
/**
* 使用者名稱
*/
@Column(name = "user_name")
private String userName;
/**
* 年齡
*/
@Column(name = "age")
private Integer age;
/**
* 建立時間
*/
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") //寫入資料庫時格式化
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") //資料庫查詢後json格式化
@Column(name = "create_time")
private Date createTime;
/**
* 建立時間
*/
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@Column(name = "update_time")
private Date updateTime;
}
Mapper介面類:UserMapper.java
import com.hc.mybatisdemo.entity.User;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import tk.mybatis.mapper.common.BaseMapper;
import tk.mybatis.mapper.common.MySqlMapper;
/**
* UserMapper介面
*/
@Mapper
public interface UserMapper extends BaseMapper<User>, MySqlMapper<User> {
/**
* 根據id查詢
*/
User findById(Long id);
/**
* 根據使用者名稱獲取使用者資訊 注意:like模糊查詢的預留位置用${},不能用#{}
*/
@Select(value = "select id, mobile, user_name as userName, age, create_time as createTime, update_time as updateTime from user_t where user_name like '%${userName}'")
List<User> findByUserName(@Param("userName") String userName);
/**
* 更新id資料的使用者名稱和年齡資訊方式1
*/
@Update(value = "update user_t set user_name = #{userName}, age = #{age} where id = #{id}")
Integer updateById1(@Param("userName") String userName, @Param("age") Integer age, @Param("id") Long id);
/**
* 刪除id資料方式1
*/
@Delete(value = "delete from user_t where id = #{id}")
Integer deleteById1(@Param("id") Long id);
/**
* 更新資料方式2
*/
Integer updateById2(User user);
/**
* 刪除id資料方式2
*
* @param id 被刪除的資料id
*/
Integer deleteById2(Long id);
}
<?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.hc.mybatisdemo.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.hc.mybatisdemo.entity.User">
<result column="id" jdbcType="VARCHAR" property="id"/>
<result column="mobile" jdbcType="VARCHAR" property="mobile"/>
<result column="user_name" jdbcType="VARCHAR" property="userName"/>
<result column="age" jdbcType="INTEGER" property="age"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
</resultMap>
<select id="findById" resultMap="BaseResultMap">
select * from user_t where id = #{id}
</select>
<!--<select id="findById" resultType="com.hc.mybatisdemo.entity.User">-->
<!--select * from user_t where id = #{id}-->
<!--</select>-->
<update id="updateById" parameterType="com.hc.mybatisdemo.entity.User">
update user_t set user_name = #{userName}, age = #{age} where id = #{id};
</update>
<delete id="deleteById" parameterType="String">
delete from user_t where id = #{id};
</delete>
</mapper>
建立業務層介面類:IUserService.java
import com.hc.mybatisdemo.entity.User;
import java.util.List;
import org.springframework.stereotype.Service;
/**
* 使用者service介面
*/
@Service
public interface IUserService {
/**
* 查詢一個
*/
User findOne(Long id);
/**
* 根據使用者名稱獲取使用者列表
*/
List<User> findByUserName(String userName);
/**
* 插入一條資料
*/
Integer insert(User user);
/**
* 更新一條資料
*/
Integer updateById(User user);
/**
* 刪除一條資料
*/
Integer deleteById(Long id);
/**
* 事務控制測試--刪除id1和id2兩條資料
*/
Integer transactionTest(Long id1, Long id2);
}
建立業務層介面實現類:UserServiceImpl.java
import com.hc.mybatisdemo.entity.User;
import com.hc.mybatisdemo.mapper.UserMapper;
import com.hc.mybatisdemo.service.IUserService;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
/**
* 使用者service實現類
*/
@Slf4j
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userMapper;
/**
* 查詢一個
*/
@Override
public User findOne(Long id) {
return userMapper.findById(id);
}
/**
* 根據使用者名稱獲取使用者列表
*/
@Override
public List<User> findByUserName(String userName) {
return userMapper.findByUserName(userName);
}
/**
* 新增一條資料
*/
@Override
public Integer insert(User user) {
return userMapper.insertSelective(user);
}
/**
* 更新一條資料
*/
@Override
public Integer updateById(User user) {
// return userDao.updateById1(user.getUserName(), user.getAge(), user.getId());
return userMapper.updateById2(user);
}
/**
* 刪除一條資料
*/
@Override
public Integer deleteById(Long id) {
// return userDao.deleteById1(id);
return userMapper.deleteById2(id);
}
/**
* 事務控制測試--刪除id1和id2兩條資料
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Integer transactionTest(Long id1, Long id2) {
try {
userMapper.deleteById1(id1);
userMapper.deleteById1(id2);
int a = 0;
int b = 10 / a;//模擬丟擲異常
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return 0;
}
return 1;
}
}
建立控制層api類:UserController.java
import com.hc.mybatisdemo.entity.User;
import com.hc.mybatisdemo.service.IUserService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 使用者控制器
*/
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private IUserService userService;
/**
* 根據id查詢
*/
@GetMapping(value = "findOne")
public User findOne(Long id) {
User user = userService.findOne(id);
return user;
}
/**
* 根據使用者名稱獲取使用者列表
*/
@GetMapping(value = "findByUserName")
public List<User> findByUserName(String userName) {
return userService.findByUserName(userName);
}
/**
* 新增一條資料
*/
@PostMapping(value = "insert")
public Integer insert(@RequestBody User user) {
return userService.insert(user);
}
/**
* 更新一條資料
*/
@PutMapping(value = "update")
public Integer update(@RequestBody User user) {
return userService.updateById(user);
}
/**
* 根據使用者名稱獲取使用者列表
*/
@DeleteMapping(value = "delete")
public Integer delete(Long id) {
return userService.deleteById(id);
}
/**
* 事務控制測試
*/
@GetMapping(value = "transactionTest")
public Integer transactionTest(Long id1, Long id2) {
return userService.transactionTest(id1, id2);
}
}
查詢id為2的資料。
左模糊查詢。查詢以「五」結尾的使用者名稱資料。
插入一條使用者名稱為「老七」的記錄。
儲存結果:
將id為5的資料的使用者名稱更新為「老七七」,年齡更新為75。
更新後結果:
刪除id為5的資料。
刪除後結果:
7.6 事務控制(Transaction)測試
呼叫事務控制測試api介面(介面的業務層會刪除id為1和2的兩條資料),但是我們人為埋下了一個丟擲異常的程式碼(int b = 10/a;)。理想結果:由於程式碼丟擲異常,那麼兩條資料都不會被刪除,因為事務回滾了!
呼叫介面,刪除id為1和2的兩條資料:
測試結果如下,可見事務回滾了。id為1和2的資料都沒有刪除成功。證明了同一個事務種mysql操作的原子性和一致性。
關注微信公眾號並回復"我要mybatis整合原始碼",免費獲取本教學mybatis-demo原始碼~