spring-boot-demo-orm-jdbctemplate
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>
< artifactId> spring-boot-demo-orm-jdbctemplate</ artifactId>
< version> 1.0.0-SNAPSHOT</ version>
< packaging> jar</ packaging>
< parent>
< groupId> com.xkcoding</ groupId>
< artifactId> spring-boot-demo</ artifactId>
< version> 1.0.0-SNAPSHOT</ version>
</ parent>
< properties>
< project.build.sourceEncoding> UTF-8</ project.build.sourceEncoding>
< project.reporting.outputEncoding> UTF-8</ project.reporting.outputEncoding>
< java.version> 1.8</ 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.springframework.boot</ groupId>
< artifactId> spring-boot-starter-test</ artifactId>
< scope> test</ scope>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
</ dependency>
< dependency>
< groupId> cn.hutool</ groupId>
< artifactId> hutool-all</ artifactId>
</ dependency>
< dependency>
< groupId> org.projectlombok</ groupId>
< artifactId> lombok</ artifactId>
< optional> true</ optional>
</ dependency>
</ dependencies>
< build>
< finalName> spring-boot-demo-orm-jdbctemplate</ finalName>
< plugins>
< plugin>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-maven-plugin</ artifactId>
</ plugin>
</ plugins>
</ build>
</ project>
BaseDao.java
@Slf4j
public class BaseDao < T , P > {
private JdbcTemplate jdbcTemplate;
private Class < T > clazz;
@SuppressWarnings ( value = "unchecked" )
public BaseDao ( JdbcTemplate jdbcTemplate) {
this . jdbcTemplate = jdbcTemplate;
clazz = ( Class < T > ) ( ( ParameterizedType ) getClass ( ) . getGenericSuperclass ( ) ) . getActualTypeArguments ( ) [ 0 ] ;
}
protected Integer insert ( T t, Boolean ignoreNull) {
String table = getTableName ( t) ;
List < Field > filterField = getField ( t, ignoreNull) ;
List < String > columnList = getColumns ( filterField) ;
String columns = StrUtil . join ( Const . SEPARATOR_COMMA, columnList) ;
String params = StrUtil . repeatAndJoin ( "?" , columnList. size ( ) , Const . SEPARATOR_COMMA) ;
Object [ ] values = filterField. stream ( ) . map ( field -> ReflectUtil . getFieldValue ( t, field) ) . toArray ( ) ;
String sql = StrUtil . format ( "INSERT INTO {table} ({columns}) VALUES ({params})" , Dict . create ( ) . set ( "table" , table) . set ( "columns" , columns) . set ( "params" , params) ) ;
log. debug ( "【执行SQL】SQL:{}" , sql) ;
log. debug ( "【执行SQL】参数:{}" , JSONUtil . toJsonStr ( values) ) ;
return jdbcTemplate. update ( sql, values) ;
}
protected Integer deleteById ( P pk) {
String tableName = getTableName ( ) ;
String sql = StrUtil . format ( "DELETE FROM {table} where id = ?" , Dict . create ( ) . set ( "table" , tableName) ) ;
log. debug ( "【执行SQL】SQL:{}" , sql) ;
log. debug ( "【执行SQL】参数:{}" , JSONUtil . toJsonStr ( pk) ) ;
return jdbcTemplate. update ( sql, pk) ;
}
protected Integer updateById ( T t, P pk, Boolean ignoreNull) {
String tableName = getTableName ( t) ;
List < Field > filterField = getField ( t, ignoreNull) ;
List < String > columnList = getColumns ( filterField) ;
List < String > columns = columnList. stream ( ) . map ( s -> StrUtil . appendIfMissing ( s, " = ?" ) ) . collect ( Collectors . toList ( ) ) ;
String params = StrUtil . join ( Const . SEPARATOR_COMMA, columns) ;
List < Object > valueList = filterField. stream ( ) . map ( field -> ReflectUtil . getFieldValue ( t, field) ) . collect ( Collectors . toList ( ) ) ;
valueList. add ( pk) ;
Object [ ] values = ArrayUtil . toArray ( valueList, Object . class ) ;
String sql = StrUtil . format ( "UPDATE {table} SET {params} where id = ?" , Dict . create ( ) . set ( "table" , tableName) . set ( "params" , params) ) ;
log. debug ( "【执行SQL】SQL:{}" , sql) ;
log. debug ( "【执行SQL】参数:{}" , JSONUtil . toJsonStr ( values) ) ;
return jdbcTemplate. update ( sql, values) ;
}
public T findOneById ( P pk) {
String tableName = getTableName ( ) ;
String sql = StrUtil . format ( "SELECT * FROM {table} where id = ?" , Dict . create ( ) . set ( "table" , tableName) ) ;
RowMapper < T > rowMapper = new BeanPropertyRowMapper < > ( clazz) ;
log. debug ( "【执行SQL】SQL:{}" , sql) ;
log. debug ( "【执行SQL】参数:{}" , JSONUtil . toJsonStr ( pk) ) ;
return jdbcTemplate. queryForObject ( sql, new Object [ ] { pk} , rowMapper) ;
}
public List < T > findByExample ( T t) {
String tableName = getTableName ( t) ;
List < Field > filterField = getField ( t, true ) ;
List < String > columnList = getColumns ( filterField) ;
List < String > columns = columnList. stream ( ) . map ( s -> " and " + s + " = ? " ) . collect ( Collectors . toList ( ) ) ;
String where = StrUtil . join ( " " , columns) ;
Object [ ] values = filterField. stream ( ) . map ( field -> ReflectUtil . getFieldValue ( t, field) ) . toArray ( ) ;
String sql = StrUtil . format ( "SELECT * FROM {table} where 1=1 {where}" , Dict . create ( ) . set ( "table" , tableName) . set ( "where" , StrUtil . isBlank ( where) ? "" : where) ) ;
log. debug ( "【执行SQL】SQL:{}" , sql) ;
log. debug ( "【执行SQL】参数:{}" , JSONUtil . toJsonStr ( values) ) ;
List < Map < String , Object > > maps = jdbcTemplate. queryForList ( sql, values) ;
List < T > ret = CollUtil . newArrayList ( ) ;
maps. forEach ( map -> ret. add ( BeanUtil . fillBeanWithMap ( map, ReflectUtil . newInstance ( clazz) , true , false ) ) ) ;
return ret;
}
private String getTableName ( T t) {
Table tableAnnotation = t. getClass ( ) . getAnnotation ( Table . class ) ;
if ( ObjectUtil . isNotNull ( tableAnnotation) ) {
return StrUtil . format ( "`{}`" , tableAnnotation. name ( ) ) ;
} else {
return StrUtil . format ( "`{}`" , t. getClass ( ) . getName ( ) . toLowerCase ( ) ) ;
}
}
private String getTableName ( ) {
Table tableAnnotation = clazz. getAnnotation ( Table . class ) ;
if ( ObjectUtil . isNotNull ( tableAnnotation) ) {
return StrUtil . format ( "`{}`" , tableAnnotation. name ( ) ) ;
} else {
return StrUtil . format ( "`{}`" , clazz. getName ( ) . toLowerCase ( ) ) ;
}
}
private List < String > getColumns ( List < Field > fieldList) {
List < String > columnList = CollUtil . newArrayList ( ) ;
for ( Field field : fieldList) {
Column columnAnnotation = field. getAnnotation ( Column . class ) ;
String columnName;
if ( ObjectUtil . isNotNull ( columnAnnotation) ) {
columnName = columnAnnotation. name ( ) ;
} else {
columnName = field. getName ( ) ;
}
columnList. add ( StrUtil . format ( "`{}`" , columnName) ) ;
}
return columnList;
}
private List < Field > getField ( T t, Boolean ignoreNull) {
Field [ ] fields = ReflectUtil . getFields ( t. getClass ( ) ) ;
List < Field > filterField;
Stream < Field > fieldStream = CollUtil . toList ( fields) . stream ( ) . filter ( field -> ObjectUtil . isNull ( field. getAnnotation ( Ignore . class ) ) || ObjectUtil . isNull ( field. getAnnotation ( Pk . class ) ) ) ;
if ( ignoreNull) {
filterField = fieldStream. filter ( field -> ObjectUtil . isNotNull ( ReflectUtil . getFieldValue ( t, field) ) ) . collect ( Collectors . toList ( ) ) ;
} else {
filterField = fieldStream. collect ( Collectors . toList ( ) ) ;
}
return filterField;
}
}
application.yml
server :
port : 8080
servlet :
context-path : /demo
spring :
datasource :
url : jdbc: mysql: //127.0.0.1: 3306/spring- boot- demo? useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
username : root
password : root
driver-class-name : com.mysql.cj.jdbc.Driver
type : com.zaxxer.hikari.HikariDataSource
initialization-mode : always
continue-on-error : true
schema :
- "classpath:db/schema.sql"
data :
- "classpath:db/data.sql"
hikari :
minimum-idle : 5
connection-test-query : SELECT 1 FROM DUAL
maximum-pool-size : 20
auto-commit : true
idle-timeout : 30000
pool-name : SpringBootDemoHikariCP
max-lifetime : 60000
connection-timeout : 30000
logging :
level :
com.xkcoding : debug
spring-boot-demo-orm-jpa
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>
< artifactId> spring-boot-demo-orm-jpa</ artifactId>
< version> 1.0.0-SNAPSHOT</ version>
< packaging> jar</ packaging>
< parent>
< groupId> com.xkcoding</ groupId>
< artifactId> spring-boot-demo</ artifactId>
< version> 1.0.0-SNAPSHOT</ version>
</ parent>
< properties>
< project.build.sourceEncoding> UTF-8</ project.build.sourceEncoding>
< project.reporting.outputEncoding> UTF-8</ project.reporting.outputEncoding>
< java.version> 1.8</ java.version>
</ properties>
< dependencies>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-data-jpa</ artifactId>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter</ artifactId>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-test</ artifactId>
< scope> test</ scope>
</ dependency>
< dependency>
< groupId> cn.hutool</ groupId>
< artifactId> hutool-all</ artifactId>
</ dependency>
< dependency>
< groupId> com.google.guava</ groupId>
< artifactId> guava</ artifactId>
</ dependency>
< dependency>
< groupId> org.projectlombok</ groupId>
< artifactId> lombok</ artifactId>
< optional> true</ optional>
</ dependency>
</ dependencies>
< build>
< finalName> spring-boot-demo-orm-jpa</ finalName>
< plugins>
< plugin>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-maven-plugin</ artifactId>
</ plugin>
</ plugins>
</ build>
</ project>
JpaConfig.java
@Configuration
@EnableTransactionManagement
@EnableJpaAuditing
@EnableJpaRepositories ( basePackages = "com.xkcoding.orm.jpa.repository" , transactionManagerRef = "jpaTransactionManager" )
public class JpaConfig {
@Bean
@ConfigurationProperties ( prefix = "spring.datasource" )
public DataSource dataSource ( ) {
return DataSourceBuilder . create ( ) . build ( ) ;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory ( ) {
HibernateJpaVendorAdapter japVendor = new HibernateJpaVendorAdapter ( ) ;
japVendor. setGenerateDdl ( false ) ;
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean ( ) ;
entityManagerFactory. setDataSource ( dataSource ( ) ) ;
entityManagerFactory. setJpaVendorAdapter ( japVendor) ;
entityManagerFactory. setPackagesToScan ( "com.xkcoding.orm.jpa.entity" ) ;
return entityManagerFactory;
}
@Bean
public PlatformTransactionManager jpaTransactionManager ( EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager ( ) ;
transactionManager. setEntityManagerFactory ( entityManagerFactory) ;
return transactionManager;
}
}
User.java
@EqualsAndHashCode ( callSuper = true )
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
@Entity
@Table ( name = "orm_user" )
@ToString ( callSuper = true )
public class User extends AbstractAuditModel {
private String name;
private String password;
private String salt;
private String email;
@Column ( name = "phone_number" )
private String phoneNumber;
private Integer status;
@Column ( name = "last_login_time" )
private Date lastLoginTime;
@ManyToMany ( cascade = CascadeType . ALL, fetch = FetchType . EAGER)
@JoinTable ( name = "orm_user_dept" , joinColumns = @JoinColumn ( name = "user_id" , referencedColumnName = "id" ) , inverseJoinColumns = @JoinColumn ( name = "dept_id" , referencedColumnName = "id" ) )
private Collection < Department > departmentList;
}
Department.java
@EqualsAndHashCode ( callSuper = true )
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table ( name = "orm_department" )
@ToString ( callSuper = true )
public class Department extends AbstractAuditModel {
@Column ( name = "name" , columnDefinition = "varchar(255) not null" )
private String name;
@ManyToOne ( cascade = { CascadeType . REFRESH} , optional = true )
@JoinColumn ( name = "superior" , referencedColumnName = "id" )
private Department superior;
@Column ( name = "levels" , columnDefinition = "int not null default 0" )
private Integer levels;
@Column ( name = "order_no" , columnDefinition = "int not null default 0" )
private Integer orderNo;
@OneToMany ( cascade = { CascadeType . REFRESH, CascadeType . REMOVE} , fetch = FetchType . EAGER, mappedBy = "superior" )
private Collection < Department > children;
@ManyToMany ( mappedBy = "departmentList" )
private Collection < User > userList;
}
AbstractAuditModel.java
@MappedSuperclass
@EntityListeners ( AuditingEntityListener . class )
@Data
public abstract class AbstractAuditModel implements Serializable {
@Id
@GeneratedValue ( strategy = GenerationType . IDENTITY)
private Long id;
@Temporal ( TemporalType . TIMESTAMP)
@Column ( name = "create_time" , nullable = false , updatable = false )
@CreatedDate
private Date createTime;
@Temporal ( TemporalType . TIMESTAMP)
@Column ( name = "last_update_time" , nullable = false )
@LastModifiedDate
private Date lastUpdateTime;
}
UserDao.java
@Repository
public interface UserDao extends JpaRepository < User , Long > {
}
DepartmentDao.java
@Repository
public interface DepartmentDao extends JpaRepository < Department , Long > {
List < Department > findDepartmentsByLevels ( Integer level) ;
}
application.yml
server :
port : 8080
servlet :
context-path : /demo
spring :
datasource :
jdbc-url : jdbc: mysql: //127.0.0.1: 3306/spring- boot- demo? useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
username : root
password : root
driver-class-name : com.mysql.cj.jdbc.Driver
type : com.zaxxer.hikari.HikariDataSource
initialization-mode : always
continue-on-error : true
schema :
- "classpath:db/schema.sql"
data :
- "classpath:db/data.sql"
hikari :
minimum-idle : 5
connection-test-query : SELECT 1 FROM DUAL
maximum-pool-size : 20
auto-commit : true
idle-timeout : 30000
pool-name : SpringBootDemoHikariCP
max-lifetime : 60000
connection-timeout : 30000
jpa :
show-sql : true
hibernate :
ddl-auto : validate
properties :
hibernate :
dialect : org.hibernate.dialect.MySQL57InnoDBDialect
open-in-view : true
logging :
level :
com.xkcoding : debug
org.hibernate.SQL : debug
org.hibernate.type : trace
UserDaoTest.java
@Slf4j
public class UserDaoTest extends SpringBootDemoOrmJpaApplicationTests {
@Autowired
private UserDao userDao;
@Test
public void testSave ( ) {
String salt = IdUtil . fastSimpleUUID ( ) ;
User testSave3 = User . builder ( ) . name ( "testSave3" ) . password ( SecureUtil . md5 ( "123456" + salt) ) . salt ( salt) . email ( "testSave3@xkcoding.com" ) . phoneNumber ( "17300000003" ) . status ( 1 ) . lastLoginTime ( new DateTime ( ) ) . build ( ) ;
userDao. save ( testSave3) ;
Assert . assertNotNull ( testSave3. getId ( ) ) ;
Optional < User > byId = userDao. findById ( testSave3. getId ( ) ) ;
Assert . assertTrue ( byId. isPresent ( ) ) ;
log. debug ( "【byId】= {}" , byId. get ( ) ) ;
}
@Test
public void testDelete ( ) {
long count = userDao. count ( ) ;
userDao. deleteById ( 1L ) ;
long left = userDao. count ( ) ;
Assert . assertEquals ( count - 1 , left) ;
}
@Test
public void testUpdate ( ) {
userDao. findById ( 1L ) . ifPresent ( user -> {
user. setName ( "JPA修改名字" ) ;
userDao. save ( user) ;
} ) ;
Assert . assertEquals ( "JPA修改名字" , userDao. findById ( 1L ) . get ( ) . getName ( ) ) ;
}
@Test
public void testQueryOne ( ) {
Optional < User > byId = userDao. findById ( 1L ) ;
Assert . assertTrue ( byId. isPresent ( ) ) ;
log. debug ( "【byId】= {}" , byId. get ( ) ) ;
}
@Test
public void testQueryAll ( ) {
List < User > users = userDao. findAll ( ) ;
Assert . assertNotEquals ( 0 , users. size ( ) ) ;
log. debug ( "【users】= {}" , users) ;
}
@Test
public void testQueryPage ( ) {
initData ( ) ;
Integer currentPage = 0 ;
Integer pageSize = 5 ;
Sort sort = Sort . by ( Sort. Direction . DESC, "id" ) ;
PageRequest pageRequest = PageRequest . of ( currentPage, pageSize, sort) ;
Page < User > userPage = userDao. findAll ( pageRequest) ;
Assert . assertEquals ( 5 , userPage. getSize ( ) ) ;
Assert . assertEquals ( userDao. count ( ) , userPage. getTotalElements ( ) ) ;
log. debug ( "【id】= {}" , userPage. getContent ( ) . stream ( ) . map ( User :: getId ) . collect ( Collectors . toList ( ) ) ) ;
}
private void initData ( ) {
List < User > userList = Lists . newArrayList ( ) ;
for ( int i = 0 ; i < 10 ; i++ ) {
String salt = IdUtil . fastSimpleUUID ( ) ;
int index = 3 + i;
User user = User . builder ( ) . name ( "testSave" + index) . password ( SecureUtil . md5 ( "123456" + salt) ) . salt ( salt) . email ( "testSave" + index + "@xkcoding.com" ) . phoneNumber ( "1730000000" + index) . status ( 1 ) . lastLoginTime ( new DateTime ( ) ) . build ( ) ;
userList. add ( user) ;
}
userDao. saveAll ( userList) ;
}
}
DepartmentDaoTest.java
@Slf4j
public class DepartmentDaoTest extends SpringBootDemoOrmJpaApplicationTests {
@Autowired
private DepartmentDao departmentDao;
@Autowired
private UserDao userDao;
@Test
@Transactional
public void testSave ( ) {
Collection < Department > departmentList = departmentDao. findDepartmentsByLevels ( 0 ) ;
if ( departmentList. size ( ) == 0 ) {
Department testSave1 = Department . builder ( ) . name ( "testSave1" ) . orderNo ( 0 ) . levels ( 0 ) . superior ( null ) . build ( ) ;
Department testSave1_1 = Department . builder ( ) . name ( "testSave1_1" ) . orderNo ( 0 ) . levels ( 1 ) . superior ( testSave1) . build ( ) ;
Department testSave1_2 = Department . builder ( ) . name ( "testSave1_2" ) . orderNo ( 0 ) . levels ( 1 ) . superior ( testSave1) . build ( ) ;
Department testSave1_1_1 = Department . builder ( ) . name ( "testSave1_1_1" ) . orderNo ( 0 ) . levels ( 2 ) . superior ( testSave1_1) . build ( ) ;
departmentList. add ( testSave1) ;
departmentList. add ( testSave1_1) ;
departmentList. add ( testSave1_2) ;
departmentList. add ( testSave1_1_1) ;
departmentDao. saveAll ( departmentList) ;
Collection < Department > deptall = departmentDao. findAll ( ) ;
log. debug ( "【部门】= {}" , JSONArray . toJSONString ( ( List ) deptall) ) ;
}
userDao. findById ( 1L ) . ifPresent ( user -> {
user. setName ( "添加部门" ) ;
Department dept = departmentDao. findById ( 2L ) . get ( ) ;
user. setDepartmentList ( departmentList) ;
userDao. save ( user) ;
} ) ;
log. debug ( "用户部门={}" , JSONUtil . toJsonStr ( userDao. findById ( 1L ) . get ( ) . getDepartmentList ( ) ) ) ;
departmentDao. findById ( 2L ) . ifPresent ( dept -> {
Collection < User > userlist = dept. getUserList ( ) ;
log. debug ( "部门下用户={}" , JSONUtil . toJsonStr ( userlist) ) ;
} ) ;
userDao. findById ( 1L ) . ifPresent ( user -> {
user. setName ( "清空部门" ) ;
user. setDepartmentList ( null ) ;
userDao. save ( user) ;
} ) ;
log. debug ( "用户部门={}" , userDao. findById ( 1L ) . get ( ) . getDepartmentList ( ) ) ;
}
}
参考
Spring Data JPA 官方文档:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
spring-boot-demo-orm-mybatis
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>
< artifactId> spring-boot-demo-orm-mybatis</ artifactId>
< version> 1.0.0-SNAPSHOT</ version>
< packaging> jar</ packaging>
< parent>
< groupId> com.xkcoding</ groupId>
< artifactId> spring-boot-demo</ artifactId>
< version> 1.0.0-SNAPSHOT</ version>
</ parent>
< properties>
< project.build.sourceEncoding> UTF-8</ project.build.sourceEncoding>
< project.reporting.outputEncoding> UTF-8</ project.reporting.outputEncoding>
< java.version> 1.8</ java.version>
< mybatis.version> 1.3.2</ mybatis.version>
</ properties>
< dependencies>
< dependency>
< groupId> org.mybatis.spring.boot</ groupId>
< artifactId> mybatis-spring-boot-starter</ artifactId>
< version> ${mybatis.version}</ version>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
</ dependency>
< dependency>
< groupId> org.projectlombok</ groupId>
< artifactId> lombok</ artifactId>
< optional> true</ optional>
</ dependency>
< dependency>
< groupId> cn.hutool</ groupId>
< artifactId> hutool-all</ artifactId>
</ dependency>
< dependency>
< groupId> com.google.guava</ groupId>
< artifactId> guava</ artifactId>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-test</ artifactId>
< scope> test</ scope>
</ dependency>
</ dependencies>
< build>
< finalName> spring-boot-demo-orm-mybatis</ finalName>
< plugins>
< plugin>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-maven-plugin</ artifactId>
</ plugin>
</ plugins>
</ build>
</ project>
SpringBootDemoOrmMybatisApplication.java
@MapperScan ( basePackages = { "com.xkcoding.orm.mybatis.mapper" } )
@SpringBootApplication
public class SpringBootDemoOrmMybatisApplication {
public static void main ( String [ ] args) {
SpringApplication . run ( SpringBootDemoOrmMybatisApplication . class , args) ;
}
}
application.yml
spring :
datasource :
url : jdbc: mysql: //127.0.0.1: 3306/spring- boot- demo? useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
username : root
password : root
driver-class-name : com.mysql.cj.jdbc.Driver
type : com.zaxxer.hikari.HikariDataSource
initialization-mode : always
continue-on-error : true
schema :
- "classpath:db/schema.sql"
data :
- "classpath:db/data.sql"
hikari :
minimum-idle : 5
connection-test-query : SELECT 1 FROM DUAL
maximum-pool-size : 20
auto-commit : true
idle-timeout : 30000
pool-name : SpringBootDemoHikariCP
max-lifetime : 60000
connection-timeout : 30000
logging :
level :
com.xkcoding : debug
com.xkcoding.orm.mybatis.mapper : trace
mybatis :
configuration :
map-underscore-to-camel-case : true
mapper-locations : classpath: mappers/*.xml
type-aliases-package : com.xkcoding.orm.mybatis.entity
UserMapper.java
@Mapper
@Component
public interface UserMapper {
@Select ( "SELECT * FROM orm_user" )
List < User > selectAllUser ( ) ;
@Select ( "SELECT * FROM orm_user WHERE id = #{id}" )
User selectUserById ( @Param ( "id" ) Long id) ;
int saveUser ( @Param ( "user" ) User user) ;
int deleteById ( @Param ( "id" ) Long id) ;
}
UserMapper.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.xkcoding.orm.mybatis.mapper.UserMapper" >
< insert id = " saveUser" >
INSERT INTO `orm_user` (`name`,
`password`,
`salt`,
`email`,
`phone_number`,
`status`,
`create_time`,
`last_login_time`,
`last_update_time`)
VALUES (#{user.name},
#{user.password},
#{user.salt},
#{user.email},
#{user.phoneNumber},
#{user.status},
#{user.createTime},
#{user.lastLoginTime},
#{user.lastUpdateTime})
</ insert>
< delete id = " deleteById" >
DELETE
FROM `orm_user`
WHERE `id` = #{id}
</ delete>
</ mapper>
UserMapperTest.java
@Slf4j
public class UserMapperTest extends SpringBootDemoOrmMybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void selectAllUser ( ) {
List < User > userList = userMapper. selectAllUser ( ) ;
Assert . assertTrue ( CollUtil . isNotEmpty ( userList) ) ;
log. debug ( "【userList】= {}" , userList) ;
}
@Test
public void selectUserById ( ) {
User user = userMapper. selectUserById ( 1L ) ;
Assert . assertNotNull ( user) ;
log. debug ( "【user】= {}" , user) ;
}
@Test
public void saveUser ( ) {
String salt = IdUtil . fastSimpleUUID ( ) ;
User user = User . builder ( ) . name ( "testSave3" ) . password ( SecureUtil . md5 ( "123456" + salt) ) . salt ( salt) . email ( "testSave3@xkcoding.com" ) . phoneNumber ( "17300000003" ) . status ( 1 ) . lastLoginTime ( new DateTime ( ) ) . createTime ( new DateTime ( ) ) . lastUpdateTime ( new DateTime ( ) ) . build ( ) ;
int i = userMapper. saveUser ( user) ;
Assert . assertEquals ( 1 , i) ;
}
@Test
public void deleteById ( ) {
int i = userMapper. deleteById ( 1L ) ;
Assert . assertEquals ( 1 , i) ;
}
}
参考
Mybatis官方文档:http://www.mybatis.org/mybatis-3/zh/index.html
Mybatis官方脚手架文档:http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
Mybatis整合Spring Boot官方demo:https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples
spring-boot-demo-orm-mybatis-plus
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>
< artifactId> spring-boot-demo-orm-mybatis-plus</ artifactId>
< version> 1.0.0-SNAPSHOT</ version>
< packaging> jar</ packaging>
< parent>
< groupId> com.xkcoding</ groupId>
< artifactId> spring-boot-demo</ artifactId>
< version> 1.0.0-SNAPSHOT</ version>
</ parent>
< properties>
< project.build.sourceEncoding> UTF-8</ project.build.sourceEncoding>
< project.reporting.outputEncoding> UTF-8</ project.reporting.outputEncoding>
< java.version> 1.8</ java.version>
< mybatis.plus.version> 3.0.5</ mybatis.plus.version>
</ properties>
< dependencies>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter</ artifactId>
</ dependency>
< dependency>
< groupId> com.baomidou</ groupId>
< artifactId> mybatis-plus-boot-starter</ artifactId>
< version> ${mybatis.plus.version}</ version>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-test</ artifactId>
< scope> test</ scope>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
</ dependency>
< dependency>
< groupId> cn.hutool</ groupId>
< artifactId> hutool-all</ artifactId>
</ dependency>
< dependency>
< groupId> com.google.guava</ groupId>
< artifactId> guava</ artifactId>
</ dependency>
< dependency>
< groupId> org.projectlombok</ groupId>
< artifactId> lombok</ artifactId>
< optional> true</ optional>
</ dependency>
</ dependencies>
< build>
< finalName> spring-boot-demo-orm-mybatis-plus</ finalName>
< plugins>
< plugin>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-maven-plugin</ artifactId>
</ plugin>
</ plugins>
</ build>
</ project>
MybatisPlusConfig.java
@Configuration
@MapperScan ( basePackages = { "com.xkcoding.orm.mybatis.plus.mapper" } )
@EnableTransactionManagement
public class MybatisPlusConfig {
@Bean
public PerformanceInterceptor performanceInterceptor ( ) {
return new PerformanceInterceptor ( ) ;
}
@Bean
public PaginationInterceptor paginationInterceptor ( ) {
return new PaginationInterceptor ( ) ;
}
}
CommonFieldHandler.java
package com. xkcoding. orm. mybatis. plus. config ;
import com. baomidou. mybatisplus. core. handlers. MetaObjectHandler ;
import lombok. extern. slf4j. Slf4j ;
import org. apache. ibatis. reflection. MetaObject ;
import org. springframework. stereotype. Component ;
import java. util. Date ;
@Slf4j
@Component
public class CommonFieldHandler implements MetaObjectHandler {
@Override
public void insertFill ( MetaObject metaObject) {
log. info ( "start insert fill ...." ) ;
this . setFieldValByName ( "createTime" , new Date ( ) , metaObject) ;
this . setFieldValByName ( "lastUpdateTime" , new Date ( ) , metaObject) ;
}
@Override
public void updateFill ( MetaObject metaObject) {
log. info ( "start update fill ...." ) ;
this . setFieldValByName ( "lastUpdateTime" , new Date ( ) , metaObject) ;
}
}
application.yml
spring :
datasource :
url : jdbc: mysql: //127.0.0.1: 3306/spring- boot- demo? useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
username : root
password : root
driver-class-name : com.mysql.cj.jdbc.Driver
type : com.zaxxer.hikari.HikariDataSource
initialization-mode : always
continue-on-error : true
schema :
- "classpath:db/schema.sql"
data :
- "classpath:db/data.sql"
hikari :
minimum-idle : 5
connection-test-query : SELECT 1 FROM DUAL
maximum-pool-size : 20
auto-commit : true
idle-timeout : 30000
pool-name : SpringBootDemoHikariCP
max-lifetime : 60000
connection-timeout : 30000
logging :
level :
com.xkcoding : debug
com.xkcoding.orm.mybatis.plus.mapper : trace
mybatis-plus :
mapper-locations : classpath: mappers/*.xml
typeAliasesPackage : com.xkcoding.orm.mybatis.plus.entity
global-config :
db-config :
id-type : auto
field-strategy : not_empty
table-underline : true
db-type : mysql
refresh : true
configuration :
map-underscore-to-camel-case : true
cache-enabled : true
UserMapper.java
@Component
public interface UserMapper extends BaseMapper < User > {
}
UserService.java
public interface UserService extends IService < User > {
}
UserServiceImpl.java
@Service
public class UserServiceImpl extends ServiceImpl < UserMapper , User > implements UserService {
}
UserServiceTest.java
@Slf4j
public class UserServiceTest extends SpringBootDemoOrmMybatisPlusApplicationTests {
@Autowired
private UserService userService;
@Test
public void testSave ( ) {
String salt = IdUtil . fastSimpleUUID ( ) ;
User testSave3 = User . builder ( ) . name ( "testSave3" ) . password ( SecureUtil . md5 ( "123456" + salt) ) . salt ( salt) . email ( "testSave3@xkcoding.com" ) . phoneNumber ( "17300000003" ) . status ( 1 ) . lastLoginTime ( new DateTime ( ) ) . build ( ) ;
boolean save = userService. save ( testSave3) ;
Assert . assertTrue ( save) ;
log. debug ( "【测试id回显#testSave3.getId()】= {}" , testSave3. getId ( ) ) ;
}
@Test
public void testSaveList ( ) {
List < User > userList = Lists . newArrayList ( ) ;
for ( int i = 4 ; i < 14 ; i++ ) {
String salt = IdUtil . fastSimpleUUID ( ) ;
User user = User . builder ( ) . name ( "testSave" + i) . password ( SecureUtil . md5 ( "123456" + salt) ) . salt ( salt) . email ( "testSave" + i + "@xkcoding.com" ) . phoneNumber ( "1730000000" + i) . status ( 1 ) . lastLoginTime ( new DateTime ( ) ) . build ( ) ;
userList. add ( user) ;
}
boolean batch = userService. saveBatch ( userList) ;
Assert . assertTrue ( batch) ;
List < Long > ids = userList. stream ( ) . map ( User :: getId ) . collect ( Collectors . toList ( ) ) ;
log. debug ( "【userList#ids】= {}" , ids) ;
}
@Test
public void testDelete ( ) {
boolean remove = userService. removeById ( 1L ) ;
Assert . assertTrue ( remove) ;
User byId = userService. getById ( 1L ) ;
Assert . assertNull ( byId) ;
}
@Test
public void testUpdate ( ) {
User user = userService. getById ( 1L ) ;
Assert . assertNotNull ( user) ;
user. setName ( "MybatisPlus修改名字" ) ;
boolean b = userService. updateById ( user) ;
Assert . assertTrue ( b) ;
User update = userService. getById ( 1L ) ;
Assert . assertEquals ( "MybatisPlus修改名字" , update. getName ( ) ) ;
log. debug ( "【update】= {}" , update) ;
}
@Test
public void testQueryOne ( ) {
User user = userService. getById ( 1L ) ;
Assert . assertNotNull ( user) ;
log. debug ( "【user】= {}" , user) ;
}
@Test
public void testQueryAll ( ) {
List < User > list = userService. list ( new QueryWrapper < > ( ) ) ;
Assert . assertTrue ( CollUtil . isNotEmpty ( list) ) ;
log. debug ( "【list】= {}" , list) ;
}
@Test
public void testQueryByPageAndSort ( ) {
initData ( ) ;
int count = userService. count ( new QueryWrapper < > ( ) ) ;
Page < User > userPage = new Page < > ( 1 , 5 ) ;
userPage. setDesc ( "id" ) ;
IPage < User > page = userService. page ( userPage, new QueryWrapper < > ( ) ) ;
Assert . assertEquals ( 5 , page. getSize ( ) ) ;
Assert . assertEquals ( count, page. getTotal ( ) ) ;
log. debug ( "【page.getRecords()】= {}" , page. getRecords ( ) ) ;
}
@Test
public void testQueryByCondition ( ) {
initData ( ) ;
QueryWrapper < User > wrapper = new QueryWrapper < > ( ) ;
wrapper. like ( "name" , "Save1" ) . or ( ) . eq ( "phone_number" , "17300000001" ) . orderByDesc ( "id" ) ;
int count = userService. count ( wrapper) ;
Page < User > userPage = new Page < > ( 1 , 3 ) ;
IPage < User > page = userService. page ( userPage, wrapper) ;
Assert . assertEquals ( 3 , page. getSize ( ) ) ;
Assert . assertEquals ( count, page. getTotal ( ) ) ;
log. debug ( "【page.getRecords()】= {}" , page. getRecords ( ) ) ;
}
private void initData ( ) {
testSaveList ( ) ;
}
}
ActiveRecord 模式
@Data
@TableName ( "orm_role" )
@Accessors ( chain = true )
@EqualsAndHashCode ( callSuper = true )
public class Role extends Model < Role > {
private Long id;
private String name;
@Override
protected Serializable pkVal ( ) {
return this . id;
}
}
public interface RoleMapper extends BaseMapper < Role > {
}
@Slf4j
public class ActiveRecordTest extends SpringBootDemoOrmMybatisPlusApplicationTests {
@Test
public void testActiveRecordInsert ( ) {
Role role = new Role ( ) ;
role. setName ( "VIP" ) ;
Assert . assertTrue ( role. insert ( ) ) ;
log. debug ( "【role】= {}" , role) ;
}
@Test
public void testActiveRecordUpdate ( ) {
Assert . assertTrue ( new Role ( ) . setId ( 1L ) . setName ( "管理员-1" ) . updateById ( ) ) ;
Assert . assertTrue ( new Role ( ) . update ( new UpdateWrapper < Role > ( ) . lambda ( ) . set ( Role :: getName , "普通用户-1" ) . eq ( Role :: getId , 2 ) ) ) ;
}
@Test
public void testActiveRecordSelect ( ) {
Assert . assertEquals ( "管理员" , new Role ( ) . setId ( 1L ) . selectById ( ) . getName ( ) ) ;
Role role = new Role ( ) . selectOne ( new QueryWrapper < Role > ( ) . lambda ( ) . eq ( Role :: getId , 2 ) ) ;
Assert . assertEquals ( "普通用户" , role. getName ( ) ) ;
List < Role > roles = new Role ( ) . selectAll ( ) ;
Assert . assertTrue ( roles. size ( ) > 0 ) ;
log. debug ( "【roles】= {}" , roles) ;
}
@Test
public void testActiveRecordDelete ( ) {
Assert . assertTrue ( new Role ( ) . setId ( 1L ) . deleteById ( ) ) ;
Assert . assertTrue ( new Role ( ) . delete ( new QueryWrapper < Role > ( ) . lambda ( ) . eq ( Role :: getName , "普通用户" ) ) ) ;
}
}
参考
mybatis-plus官方文档:http://mp.baomidou.com/