概述
這段時間接觸很多知識,也逐漸深入到項目整個流程開發,對Linux也有逐步地認識。雖然有去探索,但感覺能力還不足以寫出來跟大家分享。撰寫本文是瞭解到有些讀者反饋,對於MP(MybatisPlus縮寫)不太瞭解以及如何去使用,但更多還是筆者用完覺得非常強大,有必要share。文章還會主講Redis配置使用,篇幅有點長,因此分爲兩節講解。
構建
- 開發環境:Spring Tool Suite(Version: 3.8.2.RELEASE當然,譬如Eclipse、MyEclipse等其他IDE工具也行)
- 數據庫:MySQL
項目結構
新建Maven項目,導入相關依賴包,pom.xml(根據個人需求可以去掉不必要的包)
<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>com.jekin.example</groupId>
<artifactId>redis-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring.boot.version>1.5.3.RELEASE</spring.boot.version>
<java.version>1.8</java.version>
<redis.version>1.4.7.RELEASE</redis.version>
<druid.version>1.0.0</druid.version>
<mybatisplus-spring-boot-starter.version>1.0.1</mybatisplus-spring-boot-starter.version>
<fastjson.version>1.2.31</fastjson.version>
<mysql.version>5.1.42</mysql.version>
<commons.lang3.version>3.5</commons.lang3.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>${redis.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 數據庫連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatisplus-spring-boot-starter</artifactId>
<version>${mybatisplus-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Maven編譯版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<executable>true</executable>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- 爲Spring Boot提供Maven操作支持 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<finalName>redis</finalName>
</configuration>
<executions>
<execution>
<!-- 重新打包成可執行包文件,達到一鍵啓動運行 -->
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceExcludes>src/main/resources/**</warSourceExcludes>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
SpringBoot配置文件,application.yaml
server:
port: 8080
spring:
main:
banner-mode: "off"
application:
name: redis
profiles:
active: local
thymeleaf:
cache: false #前後端分離,關閉前端模板引擎,官方建議
http:
converters:
preferred-json-mapper: fastjson
redis: #redis配置,不使用可刪除
host: 192.168.1.70
password: rs0720$
port: 6379
pool:
max-idle: 10
min-idle: 1
max-active: 1000
max-wait: -1
datasource:
url: jdbc:mysql://192.168.1.70:3306/sharing?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
username: *** #本地數據庫用戶名
password: *** #本地數據庫密碼
filters: mergeStat
logging:
config: classpath:logback-${spring.profiles.active}.xml
################### mybatis-plus配置 ###################
mybatis-plus:
mapper-locations: classpath*:com/jekin/example/**/mapping/*.xml
typeAliasesPackage: com.jekin.example.entity
global-config:
id-type: 3 #1:數據庫ID自增 2:用戶輸入id 3:全局唯一id(IdWorker) 4:全局唯一ID(uuid)
db-column-underline: false
refresh-mapper: true
is-capital-mode: false
configuration:
map-underscore-to-camel-case: true
cache-enabled: true #配置的緩存的全局開關
lazyLoadingEnabled: true #延時加載的開關
jdbcTypeForNull: NULL
multipleResultSetsEnabled: true #開啓的話,延時加載一個屬性時會加載該對象全部屬性,否則按需加載屬性
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql語句,調試用
數據源配置文件,DruidProperties.java
package com.jekin.example.properties;
import java.sql.SQLException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import com.alibaba.druid.pool.DruidDataSource;
/**
* <p>數據庫數據源配置</p>
* <p>說明:這個類中包含了許多默認配置,若這些配置符合您的情況,您可以不用管,若不符合,建議不要修改本類,建議直接在"application.yml"中配置即可</p>
*
* @date 2017-05-21 11:18
*/
@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class DruidProperties {
private String url = "jdbc:mysql://127.0.0.1:3306/operation?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull";
private String username = "root";
private String password = "admin";
private String driverClassName = "com.mysql.jdbc.Driver";
private Integer initialSize = 2;
private Integer minIdle = 1;
private Integer maxActive = 20;
private Integer maxWait = 60000;
private Integer timeBetweenEvictionRunsMillis = 60000;
private Integer minEvictableIdleTimeMillis = 300000;
private String validationQuery = "SELECT 'x' from dual";
private Boolean testWhileIdle = true;
private Boolean testOnBorrow = false;
private Boolean testOnReturn = false;
private Boolean poolPreparedStatements = true;
private Integer maxPoolPreparedStatementPerConnectionSize = 20;
private String filters = "stat";
public void coinfig(DruidDataSource dataSource) {
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClassName);
dataSource.setInitialSize(initialSize); //定義初始連接數
dataSource.setMinIdle(minIdle); //最小空閒
dataSource.setMaxActive(maxActive); //定義最大連接數
dataSource.setMaxWait(maxWait); //最長等待時間
// 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
// 配置一個連接在池中最小生存的時間,單位是毫秒
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
dataSource.setValidationQuery(validationQuery);
dataSource.setTestWhileIdle(testWhileIdle);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setTestOnReturn(testOnReturn);
// 打開PSCache,並且指定每個連接上PSCache的大小
dataSource.setPoolPreparedStatements(poolPreparedStatements);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
dataSource.setFilters(filters);
} catch (SQLException e) {
e.printStackTrace();
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public Integer getInitialSize() {
return initialSize;
}
public void setInitialSize(Integer initialSize) {
this.initialSize = initialSize;
}
public Integer getMinIdle() {
return minIdle;
}
public void setMinIdle(Integer minIdle) {
this.minIdle = minIdle;
}
public Integer getMaxActive() {
return maxActive;
}
public void setMaxActive(Integer maxActive) {
this.maxActive = maxActive;
}
public Integer getMaxWait() {
return maxWait;
}
public void setMaxWait(Integer maxWait) {
this.maxWait = maxWait;
}
public Integer getTimeBetweenEvictionRunsMillis() {
return timeBetweenEvictionRunsMillis;
}
public void setTimeBetweenEvictionRunsMillis(Integer timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
}
public Integer getMinEvictableIdleTimeMillis() {
return minEvictableIdleTimeMillis;
}
public void setMinEvictableIdleTimeMillis(Integer minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
public String getValidationQuery() {
return validationQuery;
}
public void setValidationQuery(String validationQuery) {
this.validationQuery = validationQuery;
}
public Boolean getTestWhileIdle() {
return testWhileIdle;
}
public void setTestWhileIdle(Boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
public Boolean getTestOnBorrow() {
return testOnBorrow;
}
public void setTestOnBorrow(Boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
public Boolean getTestOnReturn() {
return testOnReturn;
}
public void setTestOnReturn(Boolean testOnReturn) {
this.testOnReturn = testOnReturn;
}
public Boolean getPoolPreparedStatements() {
return poolPreparedStatements;
}
public void setPoolPreparedStatements(Boolean poolPreparedStatements) {
this.poolPreparedStatements = poolPreparedStatements;
}
public Integer getMaxPoolPreparedStatementPerConnectionSize() {
return maxPoolPreparedStatementPerConnectionSize;
}
public void setMaxPoolPreparedStatementPerConnectionSize(Integer maxPoolPreparedStatementPerConnectionSize) {
this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
}
public String getFilters() {
return filters;
}
public void setFilters(String filters) {
this.filters = filters;
}
}
MP註解配置,MybatisPlusConfig.java
package com.jekin.example.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.enums.DBType;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.jekin.example.properties.DruidProperties;
/**
* MybatisPlus配置
*
* @author Jekin
* @date 2017年10月31日上午11:36:30
*/
@Configuration
@MapperScan(basePackages = {"com.jekin.example.mapper"})
public class MybatisPlusConfig {
@Autowired
DruidProperties druidProperties;
/**
* mybatis-plus分頁插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
paginationInterceptor.setDialectType(DBType.MYSQL.getDb());
return paginationInterceptor;
}
/**
* druid數據庫連接池
*/
@Bean(initMethod = "init")
public DruidDataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
druidProperties.coinfig(dataSource);
return dataSource;
}
}
啓動類,RedisExampleApplication.java
package com.jekin.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* 啓動類
*
* @author fengjk
* @date 2017年6月27日
* @since 1.0
*/
@SpringBootApplication
public class RedisExampleApplication extends WebMvcConfigurerAdapter{
protected final static Logger logger = LoggerFactory.getLogger(RedisExampleApplication.class);
public static void main(String[] args) {
SpringApplication.run(RedisExampleApplication.class, args);
logger.info("RedisExampleApplication is sussess!");
}
}
至此,SpringBoot集成MP框架就算搭建完成。下面,看下MP封裝的常見mapper方法的使用。
創建實體類(略),映射文件(略),UserMapper.java
package com.jekin.example.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.jekin.example.entity.User;
/**
* 用戶表 數據層
*
*/
public interface UserMapper extends BaseMapper<User> {
List<User> getUserPage(@Param("page") Page<User> page,
@Param("orderByField") String orderByField, @Param("isAsc") boolean isAsc);
}
getUserPage是分頁方法,下節會提到。這裏主要看下BaseMapper(MP對外mapper封裝類)
/**
* Copyright (c) 2011-2020, hubin (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.mapper;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.RowBounds;
/**
* <p>
* Mapper 繼承該接口後,無需編寫 mapper.xml 文件,即可獲得CRUD功能
* </p>
* <p>
* 這個 Mapper 支持 id 泛型
* </p>
*
* @author hubin
* @Date 2016-01-23
*/
public interface BaseMapper<T> {
/**
* <p>
* 插入一條記錄
* </p>
*
* @param entity
* 實體對象
* @return int
*/
Integer insert(T entity);
/**
* <p>
* 插入一條記錄
* </p>
*
* @param entity
* 實體對象
* @return int
*/
Integer insertAllColumn(T entity);
/**
* <p>
* 根據 ID 刪除
* </p>
*
* @param id
* 主鍵ID
* @return int
*/
Integer deleteById(Serializable id);
/**
* <p>
* 根據 columnMap 條件,刪除記錄
* </p>
*
* @param columnMap
* 表字段 map 對象
* @return int
*/
Integer deleteByMap(@Param("cm") Map<String, Object> columnMap);
/**
* <p>
* 根據 entity 條件,刪除記錄
* </p>
*
* @param wrapper
* 實體對象封裝操作類(可以爲 null)
* @return int
*/
Integer delete(@Param("ew") Wrapper<T> wrapper);
/**
* <p>
* 刪除(根據ID 批量刪除)
* </p>
*
* @param idList
* 主鍵ID列表
* @return int
*/
Integer deleteBatchIds(List<? extends Serializable> idList);
/**
* <p>
* 根據 ID 修改
* </p>
*
* @param entity
* 實體對象
* @return int
*/
Integer updateById(T entity);
/**
* <p>
* 根據 ID 修改
* </p>
*
* @param entity
* 實體對象
* @return int
*/
Integer updateAllColumnById(T entity);
/**
* <p>
* 根據 whereEntity 條件,更新記錄
* </p>
*
* @param entity
* 實體對象
* @param wrapper
* 實體對象封裝操作類(可以爲 null)
* @return
*/
Integer update(@Param("et") T entity, @Param("ew") Wrapper<T> wrapper);
/**
* <p>
* 根據 ID 查詢
* </p>
*
* @param id
* 主鍵ID
* @return T
*/
T selectById(Serializable id);
/**
* <p>
* 查詢(根據ID 批量查詢)
* </p>
*
* @param idList
* 主鍵ID列表
* @return List<T>
*/
List<T> selectBatchIds(List<? extends Serializable> idList);
/**
* <p>
* 查詢(根據 columnMap 條件)
* </p>
*
* @param columnMap
* 表字段 map 對象
* @return List<T>
*/
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
/**
* <p>
* 根據 entity 條件,查詢一條記錄
* </p>
*
* @param entity
* 實體對象
* @return T
*/
T selectOne(@Param("ew") T entity);
/**
* <p>
* 根據 Wrapper 條件,查詢總記錄數
* </p>
*
* @param wrapper
* 實體對象
* @return int
*/
Integer selectCount(@Param("ew") Wrapper<T> wrapper);
/**
* <p>
* 根據 entity 條件,查詢全部記錄
* </p>
*
* @param wrapper
* 實體對象封裝操作類(可以爲 null)
* @return List<T>
*/
List<T> selectList(@Param("ew") Wrapper<T> wrapper);
/**
* <p>
* 根據 Wrapper 條件,查詢全部記錄
* </p>
*
* @param wrapper
* 實體對象封裝操作類(可以爲 null)
* @return List<T>
*/
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> wrapper);
/**
* <p>
* 根據 Wrapper 條件,查詢全部記錄
* </p>
*
* @param wrapper
* 實體對象封裝操作類(可以爲 null)
* @return List<Object>
*/
List<Object> selectObjs(@Param("ew") Wrapper<T> wrapper);
/**
* <p>
* 根據 entity 條件,查詢全部記錄(並翻頁)
* </p>
*
* @param rowBounds
* 分頁查詢條件(可以爲 RowBounds.DEFAULT)
* @param wrapper
* 實體對象封裝操作類(可以爲 null)
* @return List<T>
*/
List<T> selectPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
/**
* <p>
* 根據 Wrapper 條件,查詢全部記錄(並翻頁)
* </p>
*
* @param rowBounds
* 分頁查詢條件(可以爲 RowBounds.DEFAULT)
* @param wrapper
* 實體對象封裝操作類
* @return List<Map<String, Object>>
*/
List<Map<String, Object>> selectMapsPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
}
就如作者說的,只要繼承該接口,就可以使用裏面的CURD,用起來十分方便快捷。
單元測試(使用例子),RedisTest.java
package com.jekin.example.test;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.jekin.example.RedisExampleApplication;
import com.jekin.example.entity.User;
import com.jekin.example.mapper.UserMapper;
import com.jekin.example.service.RedisService;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RedisExampleApplication.class,webEnvironment=WebEnvironment.RANDOM_PORT)
@ActiveProfiles("local")
public class RedisTest {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisTest.class);
@Autowired
RedisService redisService;
@Autowired
UserMapper userMapper;
/*@Test
public void testRedis(){
redisService.set("haha", "1");
String str = redisService.get("haha");
LOGGER.info(str);
}*/
@Test
public void testMapper(){
// 新增
User use = new User();
userMapper.insert(use);
// 根據主鍵刪除
userMapper.deleteById(898474800007831552L);
// 條件刪除
userMapper.delete(new EntityWrapper<User>().eq("name", "Jekin"));
// 根據ID修改
userMapper.updateById(use);
// 條件修改
userMapper.update(use, new EntityWrapper<User>().eq("name", "Jekin"));
// 主鍵查詢
User user = userMapper.selectById(898474800007831552L);
LOGGER.info("get user object:{}", JSON.toJSONString(user));
// 條件查詢
List<User> users = userMapper.selectList(new EntityWrapper<User>().eq("name", "Jekin"));
LOGGER.info("get users list:{}", JSON.toJSONString(users));
// 多條件查詢
List<User> users1 = userMapper.selectList(new EntityWrapper<User>().notIn("type", 1).eq("name", "Jekin"));
LOGGER.info("get users1 list:{}", JSON.toJSONString(users1));
}
}
當存在多個環境時,才需要使用@ActiveProfiles來指定加載文件,此處可省略。以上基本覆蓋了常用的方法,還有個別筆者沒有一一列舉,但都是大同小異,相信大家都可以舉一反三。
日誌文件,logback-local.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<contextName>logback</contextName>
<property name="log.path" value="logs/redis.log" />
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="console" />
</root>
<logger name="org.springframework" level="error" />
<logger name="org.apache.http" level="error" />
<logger name="org.mybatis" level="debug" />
<logger name="java.sql" level="error" />
</configuration>
總結
本章主要講的是MP的集成,框架搭建,至此,如果只想學習SpringBoot項目搭建的話,可以到此止步,不必看下節內容,去掉Redis依賴包就完事了。下節講解MP的分頁以及Redis的配置使用。
如有問題或筆誤,可以評論留言,亦可加Q羣討論學習:583138104。筆者每篇文章源碼都會上傳上去。
源碼下載