springboot-整合mybatis,security
最近做專案用到springboot整合mybatis,security。將其中遇到的問題做一個總結
注:本專案全程無xml檔案,使用註解來新增配置。
注:本專案使用Gradle進行構建。
build.gradle
buildscript {
ext {
springBootVersion ='1.5.6.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
applyplugin:'java'
applyplugin:'eclipse-wtp'
applyplugin:'org.springframework.boot'
applyplugin:'war'
version='0.0.1-SNAPSHOT'
sourceCompatibility =1.8
repositories {
mavenCentral()
}
configurations {
providedRuntime
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-redis')
compile('org.springframework.boot:spring-boot-starter-freemarker')
compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-actuator')
compilegroup:'org.springframework.boot',name:'spring-boot-starter-mobile',version:'1.5.4.RELEASE'
compile("org.springframework.boot:spring-boot-devtools")
compile('org.apache.commons:commons-io:1.3.2')
compilegroup:'io.jsonwebtoken',name:'jjwt',version:'0.7.0'
compilegroup:'org.apache.commons',name:'commons-lang3',version:'3.6'
compilegroup:'commons-beanutils',name:'commons-beanutils',version:'1.9.3'
compilegroup:'org.apache.poi',name:'poi',version:'3.10.1'
compileOnly"org.projectlombok:lombok:1.16.16"
runtime('mysql:mysql-connector-java')
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')
}
本專案使用JWT實現security驗證
application.yml如下
server:
port:8080
session:
timeout:1800
max-http-header-size:20971520
spring:
jackson:
date-format:yyyy-MM-dd HH:mm:ss
time-zone:GMT+8
datasource:
url:jdbc:mysql://127.0.0.1:3306/captable
username:dev
password:GoAhead-1985
driver-class-name:com.mysql.jdbc.Driver
jwt:
header:Authorization
secret:mySecret
expiration:604800
route:
authentication:
path:auth
refresh:refresh
那麼肉戲來了:怎麼使用無xml實現mybatis
springboot已經整合mybatis,我們不用自己整合mybatis,只需編寫Mapper了就好;
在interface Mapper中使用註解
l 對映語句
@Insert,@Update,@Delete,@SeelctStatements
l 結果對映
一對一對映
一對多對映
l 動態SQL
@SelectProvider
@InsertProvider
@UpdateProvider
@DeleteProvider
MyBatis提供了多種註解來支援不同型別的語句(statement)如SELECT,INSERT,UPDATE,DELETE。讓我們看一下具體怎樣配置對映語句。
我們可以使用@Insert註解來定義一個INSERT對映語句:
[java]
packagecom.mybatis3.mappers;
public interface StudentMapper
{
@Insert("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,ADDR_ID, PHONE)
VALUES(#{studId},#{name},#{email},#{address.addrId},#{phone})")
int insertStudent(Student student);
}
使用了@Insert註解的insertMethod()方法將返回insert語句執行後影響的行數。
自動生成主鍵
在上一章中我們討論過主鍵列值可以自動生成。我們可以使用@Options註解的userGeneratedKeys 和keyProperty屬性讓資料庫產生auto_increment(自增長)列的值,然後將生成的值設定到輸入引數物件的屬性中。
[java]
@Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR_ID, PHONE)
VALUES(#{name},#{email},#{address.addrId},#{phone})")
@Options(useGeneratedKeys =true, keyProperty ="studId")
int insertStudent(Student student);
這裡STUD_ID列值將會通過MySQL資料庫自動生成。並且生成的值將會被設定到student物件的studId屬性中。
[java]
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
mapper.insertStudent(student);
int studentId = student.getStudId();
有一些資料庫如Orcal,並不支援AUTO_INCREMENT列屬性,它使用序列(SEQUENCE)來產生主鍵的值。
我們可以使用@SelectKey註解來為任意SQL語句來指定主鍵值,作為主鍵列的值。
假設我們有一個名為STUD_ID_SEQ的序列來生成STUD_ID主鍵值。
該專案使用mysql資料庫,所以在該處使用的是uuid()函式.
[java]
@Insert("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,ADDR_ID, PHONE)
VALUES(#{studId},#{name},#{email},#{address.addrId},#{phone})")
@SelectKey(statement="SELECT STUD_ID_SEQ.NEXTVAL FROM DUAL",
keyProperty="studId", resultType=int.class, before=true)
int insertStudent(Student student);
這裡我們使用了@SelectKey來生成主鍵值,並且儲存到了student物件的studId屬性上。由於我們設定了before=true,該語句將會在執行INSERT語句之前執行。
如果你使用序列作為觸發器來設定主鍵值,我們可以在INSERT語句執行後,從sequence_name.currval獲取資料庫產生的主鍵值。
[java]
@Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR_ID, PHONE)
VALUES(#{name},#{email},#{address.addrId},#{phone})")
@SelectKey(statement="SELECT STUD_ID_SEQ.CURRVAL FROM DUAL",
keyProperty="studId", resultType=int.class, before=false)
intinsertStudent(Student student);
我們可以使用@Update註解來定義一個UPDATE對映語句,如下所示:
[java]
@Update("UPDATE STUDENTS SET NAME=#{name}, EMAIL=#{email},
PHONE=#{phone} WHERE STUD_ID=#{studId}")
int updateStudent(Student student);
使用了@Update的updateStudent()方法將會返回執行了update語句後影響的行數。
[java]
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
int noOfRowsUpdated = mapper.updateStudent(student);
我們可以使用@Delete 註解來定義一個DELETE對映語句,如下所示:
[java]
@Delete("DELETE FROM STUDENTS WHERE STUD_ID=#{studId}")
int deleteStudent(int studId);
使用了@Delete的deleteStudent()方法將會返回執行了update語句後影響的行數。
我們可以使用@ Select註解來定義一個SELECT對映語句。
讓我們看一下怎樣使用註解配置一個簡單的select查詢。
[java]
packagecom.mybatis3.mappers;
publicinterfaceStudentMapper
{
@Select("SELECT STUD_ID AS STUDID, NAME, EMAIL, PHONE FROM
STUDENTS WHERE STUD_ID=#{studId}")
Student findStudentById(Integer studId);
}
為了將列名和Studentbean屬性名匹配,我們為stud_id起了一個studId的別名。如果返回了多行結果,將丟擲 TooManyResultsException異常。
我們可以將查詢結果通過別名或者是@Results註解與JavaBean屬性對映起來。
現在讓我們看看怎樣使用@Results註解將指定列於指定JavaBean屬性對映器來,執行SELECT查詢的:
[java]
packagecom.mybatis3.mappers;
public interface StudentMapper
{
@Select("SELECT * FROM STUDENTS")
@Results(
{
@Result(id =true, column ="stud_id", property ="studId"),
@Result(column ="name", property ="name"),
@Result(column ="email", property ="email"),
@Result(column ="addr_id", property ="address.addrId")
})
List findAllStudents();
}
例如,看下面的findStudentById()和findAllStudents()方法:
[java]
@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}")
@Results(
{
@Result(id =true, column ="stud_id", property ="studId"),
@Result(column ="name", property ="name"),
@Result(column ="email", property ="email"),
@Result(column ="addr_id", property ="address.addrId")
})
Student findStudentById(int studId);
@Select("SELECT * FROM STUDENTS")
@Results(
{
@Result(id =true, column ="stud_id", property ="studId"),
@Result(column ="name", property ="name"),
@Result(column ="email", property ="email"),
@Result(column ="addr_id", property ="address.addrId")
})
List findAllStudents();
這裡兩個語句的@Results配置完全相同,但是我必須得重複它。這裡有一個解決方法。我們可以建立一個對映器Mapper配置檔案, 然後配置元素,然後使用@ResultMap註解引用此。
在StudentMapper.xml中定義一個ID為StudentResult的。
在StudentMapper.java中,使用@ResultMap引用名為StudentResult的resultMap。
[java]
public interface StudentMapper
{
@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}")
@ResultMap("com.mybatis3.mappers.StudentMapper.StudentResult")
Student findStudentById(intstudId);
@Select("SELECT * FROM STUDENTS")
@ResultMap("com.mybatis3.mappers.StudentMapper.StudentResult")
List findAllStudents();
}
MyBatis提供了@One註解來使用巢狀select語句(Nested-Select)載入一對一關聯查詢資料。讓我們看看怎樣使用@One註解獲取學生及其地址資訊。
[java]
public interface StudentMapper
{
@Select("SELECT ADDR_ID AS ADDRID, STREET, CITY, STATE, ZIP, COUNTRY
FROM ADDRESSES WHERE ADDR_ID=#{id}")
Address findAddressById(intid);
@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId} ")
@Results(
{
@Result(id =true, column ="stud_id", property ="studId"),
@Result(column ="name", property ="name"),
@Result(column ="email", property ="email"),
@Result(property ="address", column ="addr_id",
one =@One(select = "com.mybatis3.mappers.StudentMapper.
findAddressById"))
})
Student selectStudentWithAddress(intstudId);
}
這裡我們使用了@One註解的select屬性來指定一個使用了完全限定名的方法上,該方法會返回一個Address物件。使用column=”addr_id”,則STUEDNTS表中列addr_id的值將會作為輸入引數傳遞給findAddressById()方法。如果@OneSELECT查詢返回了多行結果,則會丟擲TooManyResultsException異常。
[java]
intstudId =1;
StudentMapper studentMapper =
sqlSession.getMapper(StudentMapper.class);
Student student = studentMapper.selectStudentWithAddress(studId);
System.out.println("Student :"+student);
System.out.println("Address :"+student.getAddress());
我們可以通過基於XML的對映器配置,使用巢狀結果ResultMap來載入一對一關聯的查詢。而MyBatis3.2.2版本,並沒有對應的註解支援。但是我們可以在對映器Mapper配置檔案中配置並且使用@ResultMap註解來引用它。
在StudentMapper.xml中配置,如下所示:
[java]
public interface StudentMapper
{
@Select("select stud_id, name, email, a.addr_id, street, city, state, zip, country" + "FROM students s left outer join addresses a
on s.addr_id=a.addr_id" + "where stud_id=#{studId} ")
@ResultMap("com.mybatis3.mappers.StudentMapper.
StudentWithAddressResult")
Student selectStudentWithAddress(intid);
}
MyBatis提供了@Many註解,用來使用巢狀Select語句載入一對多關聯查詢。
現在讓我們看一下如何使用@Many註解獲取一個講師及其教授課程列表資訊:
[java]
public interface TutorMapper
{
@Select("select addr_id as addrId, street, city, state, zip,
country from addresses where addr_id=#{id}")
Address findAddressById(int id);
@Select("select * from courses where tutor_id=#{tutorId}")
@Results(
{
@Result(id =true, column ="course_id", property ="courseId"),
@Result(column ="name", property ="name"),
@Result(column ="description", property ="description"),
@Result(column ="start_date"property ="startDate"),
@Result(column ="end_date"property ="endDate")
})
List findCoursesByTutorId(int tutorId);
@Select("SELECT tutor_id, name as tutor_name, email, addr_id
FROM tutors where tutor_id=#{tutorId}")
@Results(
{
@Result(id =true, column ="tutor_id", property ="tutorId"),
@Result(column ="tutor_name", property ="name"),
@Result(column ="email", property ="email"),
@Result(property ="address", column ="addr_id",
one =@One(select = " com.mybatis3.
mappers.TutorMapper.findAddressById")),
@Result(property ="courses", column ="tutor_id",
many =@Many(select = "com.mybatis3.mappers.TutorMapper.
findCoursesByTutorId"))
})
Tutor findTutorById(inttutorId);
}
這裡我們使用了@Many註解的select屬性來指向一個完全限定名稱的方法,該方法將返回一個List物件。使用column=”tutor_id”,TUTORS表中的tutor_id列值將會作為輸入引數傳遞給findCoursesByTutorId()方法。
我們可以通過基於XML的對映器配置,使用巢狀結果ResultMap來載入一對多關聯的查詢。而MyBatis3.2.2版本,並沒有對應的註解支援。但是我們可以在對映器Mapper配置檔案中配置並且使用@ResultMap註解來引用它。
在TutorMapper.xml中配置,如下所示:
[java]
public interface TutorMapper
{
@Select("SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL,
A.ADDR_ID, STREET, CITY, STATE, ZIP, COUNTRY, COURSE_ID, C.NAME,
DESCRIPTION, START_DATE, END_DATE FROM TUTORS T LEFT OUTER
JOIN ADDRESSES A ON T.ADDR_ID=A.ADDR_ID LEFT OUTER JOIN COURSES
C ON T.TUTOR_ID=C.TUTOR_ID WHERE T.TUTOR_ID=#{tutorId}")
@ResultMap("com.mybatis3.mappers.TutorMapper.TutorResult")
Tutor selectTutorById(int tutorId);
}
有時候我們需要根據輸入條件動態地構建SQL語句。MyBatis提供了各種註解如@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,來幫助構建動態SQL語句,然後讓MyBatis執行這些SQL語句。
現在讓我們來看一個使用@SelectProvider註解來建立一個簡單的SELECT對映語句的例子。
建立一個TutorDynaSqlProvider.java類,以及findTutorByIdSql()方法,如下所示:
[java]
packagecom.mybatis3.sqlproviders;
importorg.apache.ibatis.jdbc.SQL;
publicclassTutorDynaSqlProvider
{
publicString findTutorByIdSql(inttutorId)
{
return"SELECT TUTOR_ID AS tutorId, NAME, EMAIL FROM TUTORS
WHERE TUTOR_ID=" + tutorId;
}
}
在TutorMapper.java介面中建立一個對映語句,如下:
[java]
@SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByIdSql")
Tutor findTutorById(int tutorId);
這裡我們使用了@SelectProvider來指定了一個類,及其內部的方法,用來提供需要執行的SQL語句。
但是使用字串拼接的方法構建SQL語句是非常困難的,並且容易出錯。所以MyBaits提供了一個SQL工具類不使用字串拼接的方式,簡化構造動態SQL語句。
現在,讓我們看看如何使用org.apache.ibatis.jdbc.SQL工具類來準備相同的SQL語句。
[java]
packagecom.mybatis3.sqlproviders;
import org.apache.ibatis.jdbc.SQL;
public class TutorDynaSqlProvider
{
publicString findTutorByIdSql(final int tutorId)
{
return new SQL(){
{
SELECT("tutor_id as tutorId, name, email");
FROM("tutors");
WHERE("tutor_id="+ tutorId);
} } .toString();
}
}
SQL工具類會處理以合適的空格字首和字尾來構造SQL語句。
動態SQL provider方法可以接收以下其中一種引數:
1.無引數
2.對映器Mapper介面的方法同型別的引數
3. java.util.Map
如果SQL語句的準備不取決於輸入引數,你可以使用不帶引數的SQL Provider方法。
例如:
[java]
publicString findTutorByIdSql()
{
returnnewSQL()
{
{
SELECT("tutor_id as tutorId, name, email");
FROM("tutors");
WHERE("tutor_id = #{tutorId}");
}
} .toString();
}
這裡我們沒有使用輸入引數構造SQL語句,所以它可以是一個無參方法。
如果對映器Mapper介面方法只有一個引數,那麼可以定義SQLProvider方法,它接受一個與Mapper介面方法相同型別的引數。
例如對映器Mapper介面有如下定義:
[java]
Tutor findTutorById(int tutorId);
這裡findTutorById(int)方法只有一個int型別的引數。我們可以定義findTutorByIdSql(int)方法作為SQL provider方法。
[java]
publicString findTutorByIdSql(final int tutorId)
{
returnnewSQL()
{
{
SELECT("tutor_id as tutorId, name, email");
FROM("tutors");
WHERE("tutor_id="+ tutorId);
}
} .toString();
}
如果對映器Mapper介面有多個輸入引數,我們可以使用引數型別為java.util.Map的方法作為SQLprovider方法。然後對映器Mapper介面方法所有的輸入引數將會被放到map中,以param1,param2等等作為key,將輸入引數按序作為value。你也可以使用0,1,2等作為key值來取的輸入引數。
[java]
@SelectProvider(type = TutorDynaSqlProvider.class,
method ="findTutorByNameAndEmailSql")
Tutor findTutorByNameAndEmail(String name, String email);
publicString findTutorByNameAndEmailSql(Map map)
{
String name = (String) map.get("param1");
String email = (String) map.get("param2");
//you can also get those values using 0,1 keys
//String name = (String) map.get("0");
//String email = (String) map.get("1");
returnnewSQL()
{
{
SELECT("tutor_id as tutorId, name, email");
FROM("tutors");
WHERE("name=#{name} AND email=#{email}");
}
} .toString();
}
SQL工具類也提供了其他的方法來表示JOINS,ORDER_BY,GROUP_BY等等。
讓我們看一個使用LEFT_OUTER_JOIN的例子:
[java]
public class TutorDynaSqlProvider
{
public String selectTutorById()
{
returnnewSQL()
{
{
SELECT("t.tutor_id, t.name as tutor_name, email");
SELECT("a.addr_id, street, city, state, zip, country");
SELECT("course_id, c.name as course_name, description,
start_date, end_date");
FROM("TUTORS t");
LEFT_OUTER_JOIN("addresses a on t.addr_id=a.addr_id");
LEFT_OUTER_JOIN("courses c on t.tutor_id=c.tutor_id");
WHERE("t.TUTOR_ID = #{id}");
}
} .toString();
}
}
public interface TutorMapper
{
@SelectProvider(type = TutorDynaSqlProvider.class,
method ="selectTutorById")
@ResultMap("com.mybatis3.mappers.TutorMapper.TutorResult")
Tutor selectTutorById(int tutorId);
}
由於沒有支援使用內嵌結果ResultMap的一對多關聯對映的註解支援,我們可以使用基於XML的配置,然後與@ResultMap對映。
使用了動態的SQL provider,我們可以取得講師及其地址和課程明細。
我們可以使用@InsertProvider註解建立動態的INSERT語句,如下所示:
[java]
public class TutorDynaSqlProvider
{
public String insertTutor(finalTutor tutor)
{
return new SQL()
{
{
INSERT_INTO("TUTORS");
if(tutor.getName() !=null)
{
VALUES("NAME","#{name}");
}
if(tutor.getEmail() !=null)
{
VALUES("EMAIL","#{email}");
}
}
} .toString();
}
}
public interface TutorMapper
{
@InsertProvider(type = TutorDynaSqlProvider.class,
method ="insertTutor")
@Options(useGeneratedKeys =true, keyProperty ="tutorId")
int insertTutor(Tutor tutor);
}
我們可以通過@UpdateProvider註解建立UPDATE語句,如下所示:
[java]
publicclassTutorDynaSqlProvider
{
publicString updateTutor(finalTutor tutor)
{
returnnewSQL()
{
{
UPDATE("TUTORS");
if(tutor.getName() !=null)
{
SET("NAME = #{name}");
}
if(tutor.getEmail() !=null)
{
SET("EMAIL = #{email}");
}
WHERE("TUTOR_ID = #{tutorId}");
}
} .toString();
}
}
public interface TutorMapper
{
@UpdateProvider(type = TutorDynaSqlProvider.class,
method ="updateTutor")
int updateTutor(Tutor tutor);
}
我們可以使用@DeleteProvider註解建立動態地DELETE語句,如下所示:
[java]
publicclassTutorDynaSqlProvider
{
publicString deleteTutor(inttutorId)
{
returnnewSQL()
{
{
DELETE_FROM("TUTORS");
WHERE("TUTOR_ID = #{tutorId}");
}
} .toString();
}
}
publicinterfaceTutorMapper
{
@DeleteProvider(type = TutorDynaSqlProvider.class,
method ="deleteTutor")
intdeleteTutor(inttutorId);
}
作者:誰在烽煙彼岸
連結:https://www.jianshu.com/p/3e5e1f5a85d1
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
相關文章
- Spring Security(一):整合JWTSpringJWT
- Spring 整合 MyBatisSpringMyBatis
- SpringMVC整合MybatisSpringMVCMyBatis
- mybatis整合springMyBatisSpring
- Spring整合MyBatisSpringMyBatis
- springmvc mybatis 整合SpringMVCMyBatis
- shiro 整合MybatisMyBatis
- Spring Boot整合Spring SecuritySpring Boot
- SpringBoot整合Spring SecuritySpring Boot
- [譯] JWT 整合 Spring Security OAuthJWTSpringOAuth
- MyBatis(九) 整合Spring、整合SpringMVCMyBatisSpringMVC
- Unit08: Spring與MyBatis整合 、 Spring整合MyBatis應用SpringMyBatis
- spring 整合 mybatis 及mybatis 的 crud 操作SpringMyBatis
- Spring Boot 整合 MyBatisSpring BootMyBatis
- Mybatis 整合 ehcache快取MyBatis快取
- Spring整合Mybatis plusSpringMyBatis
- Mybatis與Spring整合MyBatisSpring
- springBoot 整合 mybatisSpring BootMyBatis
- spring boot 整合mybatisSpring BootMyBatis
- Springboot整合MybatisSpring BootMyBatis
- Spring整合JUnit,MybatisSpringMyBatis
- SpringBoot整合系列–整合MyBatis-plusSpring BootMyBatis
- MyBatis6:MyBatis整合Spring事物管理(下篇)MyBatisSpring
- Spring Security原始碼分析十一:Spring Security OAuth2整合JWTSpring原始碼OAuthJWT
- springboot+mybatis整合Spring BootMyBatis
- SpringBoot | 3.2 整合MyBatisSpring BootMyBatis
- Springboot+mybatis 整合Spring BootMyBatis
- Spring boot 六 整合 MyBatisSpring BootMyBatis
- Mybatis20_ssm整合10MyBatisSSM
- oracle和mybatis整合,批次插入OracleMyBatis
- Spring Security (三):與Vue.js整合SpringVue.js
- spring-boot 整合 spring-securitySpringboot
- RBAC許可權---SpringBoot整合SecuritySpring Boot
- MyBatis5:MyBatis整合Spring事務管理(上篇)MyBatisSpring
- Spring security(四)-spring boot +spring security簡訊認證+redis整合Spring BootRedis
- SpringBoot-記Spring Boot
- 【springboot】學習4:整合JDBC、整合druid、整合mybatis、整合 SpringSecuritySpring BootJDBCUIMyBatisGse
- Mybatis整合Spring(ssm整合待續)-day04MyBatisSpringSSM