preface
Mybatis is believed to be familiar. At present, most Internet companies use MyBatis as a persistent layer framework, without any other, because you can directly write SQL statements in XML files to operate the database, flexible. But when we use it, we will also find that there are a lot of add, delete, change and check SQL is the basic operation of each table, if each table to write a set of add, delete, change and check SQL is obviously very time-consuming.
As a result, there is mybatis- Plus framework. As stated on the website, Mybatis – Plus is designed to simplify development.
Mybatis – Plus has the following features:
- Just make enhancements without making changes, and introduce it without affecting existing projects, as smooth as silk.
- Simple configuration allows you to perform CRUD operations on a single table quickly, saving a lot of time.
- Code generation, physical paging, performance analysis, and more.
I. Integration of Mybatis – Plus
SpringBoot2.5.2 is used for the demonstration. First import dependencies:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<! -- Introducing mybatis -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
Copy the code
Then configure the database information in the application.properties file:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/user? createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=root123456
Mapper. XML file path address
mybatis-plus.mapper-locations=classpath:mapper/*Mapper.xml
Copy the code
Add a scan annotation to the startup class:
@SpringBootApplication
@MapperScan(basePackages = "com.yehongzhi.mydemo.mapper")
public class MydemoApplication {
public static void main(String[] args) { SpringApplication.run(MydemoApplication.class, args); }}Copy the code
And we’re done, but we’re going to build a table to test it.
CREATE TABLE `user` (
`id` char(36) NOT NULL DEFAULT ' ' COMMENT 'ID',
`name` varchar(255) DEFAULT ' ' COMMENT 'name',
`age` int(3) DEFAULT NULL COMMENT 'age'.PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Initialize four pieces of data
INSERT INTO `user`. `user` (`id`, `name`, `age`) VALUES ('1345fc0985b111eba0e488d7f66fdab8'.'view Chen'.'20');
INSERT INTO `user`. `user` (`id`, `name`, `age`) VALUES ('d47561e885b011eba0e488d7f66fdab8'.'Yao Daqiu'.'30');
INSERT INTO `user`. `user` (`id`, `name`, `age`) VALUES ('ef2741fe87f011eba0e488d7f66fdab8'.'Stephen Chow'.'60');
INSERT INTO `user`. `user` (`id`, `name`, `age`) VALUES ('ff784f6b85b011eba0e488d7f66fdab8'.'Li Li Sheng'.'33');
Copy the code
After creating the table, create a User entity class corresponding to:
/ / the name of the table
@TableName("user")
public class User {
/ / the primary key
@TableId(type = IdType.UUID)
private String id;
/ / name
private String name;
/ / age
private Integer age;
// Getter and setter methods
}
Copy the code
Next, create the UserMapper interface class, and inherit from BaseMapper:
@Repository
public interface UserMapper extends BaseMapper<User> {}Copy the code
Create a usermapper. XML corresponding to UserMapper:
<! DOCTYPEmapper
PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yehongzhi.mydemo.mapper.UserMapper">
</mapper>
Copy the code
Select * from UserService;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public List<User> getList(a) {
return userMapper.selectList(null); }}Copy the code
Starting the project, the tests are fine:
Second, CRUD operation
After integration, according to the official description of Mybatis – Plus, there is a simple single table CRUD operation function.
All the CRUD operations for a single table are stored in BaseMapper, so when we inherit the BaseMapper class, we get the enhanced features of Mybatis – Plus, including CRUD operations for a single table.
1, insert operation
BaseMapper directly provides an insert() method that passes an entity class.
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public int insertOne(User user) {
returnuserMapper.insert(user); }}Copy the code
And then on the Controller call, because the User annotation @tableID is attached to the User class, it automatically generates the ID.
@TableName("user")
public class User {
@TableId(type = IdType.UUID)
private String id;
/ / to omit...
}
Copy the code
Controller layer code:
@RequestMapping("/insert")
public String insertUser(@RequestParam(name = "name") String name,
@RequestParam(name = "age") Integer age) {
User user = new User();
user.setName(name);
user.setAge(age);
// The @tableId annotation is used in the entity class, and the ID is automatically generated
int i = userService.insertOne(user);
return i == 1 ? "success" : "fail";
}
Copy the code
2. Update operation
BaseMapper directly provides an updateById() method that passes an entity class.
@Override
public int updateOne(User user) {
return userMapper.updateById(user);
}
Copy the code
Controller layer code:
@RequestMapping("/update")
public String updateUser(@RequestParam(name = "id") String id,
@RequestParam(name = "name",required = false) String name,
@RequestParam(name = "age",required = false) Integer age) {
User user = new User();
user.setId(id);
user.setName(name);
user.setAge(age);
int i = userService.updateOne(user);
return i == 1 ? "success" : "fail";
}
Copy the code
3. Delete
BaseMapper directly provides a deleteById() method that passes primary key values.
@Override
public int deleteOne(String id) {
return userMapper.deleteById(id);
}
Copy the code
Controller layer code:
@RequestMapping("/delete")
public String deleteUser(@RequestParam(name = "id") String id) {
int i = userService.deleteOne(id);
return i == 1 ? "success" : "fail";
}
Copy the code
Delete primary key (); delete primary key ();
@Override
public int deleteBatch(List<String> ids){
return userMapper.deleteBatchIds(ids);
}
Copy the code
Controller layer code:
@RequestMapping("/deleteBatch")
public String deleteBatchUser(@RequestParam(name = "ids") String ids) {
List<String> list = Arrays.asList(ids.split(","));
int i = userService.deleteBatch(list);
return i == list.size() ? "success" : "fail";
}
Copy the code
Conditional constructor (Wrapper)
Conditional constructors appear in various Mybatis- Plus methods, such as:
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
Copy the code
Mybatis-Plus is a powerful tool that can be used to perform a lookup after a WHERE statement. Wrapper is an abstract class and there are many subclasses below, so let’s look at the class diagram to make it look familiar.
There are four commonly used subclass implementations:
- QueryWrapper
- UpdateWrapper
- LambdaQueryWrapper
- LambdaUpdateWrapper
QueryWrapper
It is used to generate where conditions. For example, we use name to query user:
public List<User> queryUserByName(String name) {
SELECT * FROM user WHERE name =?
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//eq() denotes equality
queryWrapper.eq("name", name);
return userMapper.selectList(queryWrapper);
}
Copy the code
Let’s look at log printing:
==> Preparing: SELECT id,name,age FROM user WHERE name = ? = = > Parameters: Yao Daqiu (String) < = = the Columns: id, name, age < = = Row: d47561e885b011eba0e488d7f66fdab8 Yao Daqiu,30
<== Total: 1
Copy the code
If we want to query like, we can write:
public List<User> queryUserLikeName(String name) {
SELECT * FROM user WHERE name like %#{name}%
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name",name);
return userMapper.selectList(queryWrapper);
}
Copy the code
If you want to query an age greater than 30, you can do this:
public List<User> queryUserGtByAge(int age) {
SELECT * FROM user WHERE age >?
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", age);
// small so lt()
// greater than ge()
// less than le()
//范围的话,则使用between()
return userMapper.selectList(queryWrapper);
}
Copy the code
If you want to query a field that is not empty, you can do this:
public List<User> queryUserByNameNotNull(a) {
SELECT * FROM user WHERE name IS NOT NULL
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNotNull("name");
// if a field isNull, use isNull()
return userMapper.selectList(queryWrapper);
}
Copy the code
If you use IN, you can do this:
public List<User> queryUserByIds(List<String> ids) {
SELECT * FROM user WHERE name IN ('id1','id2');
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.in("id", ids);
// Instead, the notIn() method is provided
return userMapper.selectList(queryWrapper);
}
Copy the code
If you need to sort, you can write:
public List<User> queryUserOrderByAge(a) {
SELECT * FROM user ORDER BY age ASC
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("age");
// Instead, use the orderByDesc() method if the order is descending
return userMapper.selectList(queryWrapper);
}
Copy the code
If you need a subquery, you can write:
public List<User> queryUserInSql(a) {
SELECT * FROM user WHERE id IN (SELECT id FROM user WHERE age > 30)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("id"."select id from user where age > 30");
return userMapper.selectList(queryWrapper);
}
Copy the code
Most of the methods are derived from the AbstractWrapper class. In addition, there are many other functions, which are not introduced here. If you are interested, you can explore the conditional constructor on the official website.
UpdateWrapper
UpdateWrapper is a subclass of the AbstractWrapper abstract class, so there are all the above methods for setting conditions. The difference is that UpdateWrapper has set() and setSql() to set the updated values. Here’s an example:
public int updateUserNameById(String id, String name) {
// equivalent to: UPDATE user SET name =? where id = ?
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.eq("id", id);
Set name = #{name} set name = #{name}
userUpdateWrapper.set("name", name);
return userMapper.update(new User(), userUpdateWrapper);
}
Copy the code
SetSql () is the part of the SQL statement that sets the concatenation after the SET keyword, for example:
public int updateUserBySql(String id, String name) {
// equivalent to: UPDATE user SET name =? where id = ?
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.setSql("name = '" + name + "'");
userUpdateWrapper.eq("id", id);
return userMapper.update(new User(), userUpdateWrapper);
}
Copy the code
SetSql () is pure SQL statement concatenation. We can see that name=’ big D’ after SET, instead of placeholder, risks SQL injection.
==> Preparing: UPDATE user SET name = 'the big D' WHERE id = ?
==> Parameters: d47561e885b011eba0e488d7f66fdab8(String)
<== Updates: 1
Copy the code
LambdaQueryWrapper
The advantage of using LambdaQueryWrapper is to eliminate hard coding, such as QueryWrapper when querying name=? , you need to write:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// Use the string "name", which is hard coded
queryWrapper.eq("name", name);
Copy the code
Instead of LambdaQueryWrapper, you could write:
public List<User> lambdaQueryUserByName(String name) {
SELECT id,name,age FROM user WHERE name =?
LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper<User>().lambda();
lambdaQueryWrapper.eq(User::getName, name);
return userMapper.selectList(lambdaQueryWrapper);
}
Copy the code
For another example, using fuzzy query, you can write:
public List<User> lambdaQueryUserLikeName(String name) {
LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper<User>().lambda();
lambdaQueryWrapper.like(User::getName, name);
return userMapper.selectList(lambdaQueryWrapper);
}
Copy the code
LambdaUpdateWrapper
Similarly, LambdaUpdateWrapper can also eliminate hard coding:
public int lambdaUpdateUserNameById(String id, String name) {
// equivalent to: UPDATE user SET name=? WHERE id = ?
LambdaUpdateWrapper<User> lambdaUpdateWrapper = new UpdateWrapper<User>().lambda();
lambdaUpdateWrapper.set(User::getName, name);
lambdaUpdateWrapper.eq(User::getId, id);
return userMapper.update(new User(), lambdaUpdateWrapper);
}
Copy the code
Paging query
Mybatis- Plus provides a paging plug-in to support paging queries in just a few steps.
First add a configuration class:
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor(a) {
return newPaginationInterceptor(); }}Copy the code
Second, define the paging query method in the UserMapper class:
@Repository
public interface UserMapper extends BaseMapper<User> {
// paging query method
IPage<User> selectPageByName(Page<User> page, @Param("name") String name);
}
Copy the code
The corresponding usermapper.xml method:
<select id="selectPageByName" parameterType="java.lang.String" resultType="com.yehongzhi.mydemo.model.User">
select * from `user` where name = #{name}
</select>
Copy the code
Step 3: Call userService:
public IPage<User> selectPageByName(long pageNo, long pageSize, String name) {
Page<User> page = new Page<>();
// Set the current page number
page.setCurrent(pageNo);
// Set the number of pages to be displayed
page.setSize(pageSize);
return userMapper.selectPageByName(page, name);
}
Copy the code
Finally, write a Controller interface test:
@RequestMapping("/queryPage/ByName")
public IPage<User> selectPageByName(@RequestParam("pageNo") long pageNo,
@RequestParam("pageSize") long pageSize,
@RequestParam("name") String name) {
return userService.selectPageByName(pageNo, pageSize, name);
}
Copy the code
View console logs:
==> Preparing: SELECT COUNT(1) FROM `user` WHERE name =? <== Columns: COUNT(1)
<== Row: 1==> Preparing: select * from `user` where name = ? LIMIT ? ,? ==> Parameters: Du (String),0(Long), 10(Long) < = = the Columns: id, name, age < = = Row: d47561e885b011eba0e488d7f66fdab8, johnnie to,30
<== Total: 1
Copy the code
Paging query successful!
Custom primary key generator
Sometimes in the actual development, it may encounter that the primary key generation strategy provided by Mybatis- Plus cannot meet the requirements, so we need to customize the primary key ID generation strategy. How to set it?
We define a primary key generator as follows:
@Component
public class SnowflakeKeyGenerator implements IdentifierGenerator {
// create a snowflake ID class
@Resource
private SnowflakeIdWorker snowflakeIdWorker;
@Override
public Number nextId(Object entity) {
// Generate a snowflake ID using the snowflake ID generator
long nextId = snowflakeIdWorker.nextId();
System.out.println(String.format("Using custom ID generator, generate snowflake ID:%s", nextId));
returnnextId; }}Copy the code
We then add an annotation attribute to the entity class that needs to use the custom ID generator:
@TableName("user")
public class User {
// Set the property to idtype.assign_id
@TableId(type = IdType.ASSIGN_ID)
private String id;
/ / to omit...
}
Copy the code
After testing, we can see that the console prints logs:
conclusion
In addition to the features described above, Mybatis- Plus has many other features, such as: code generators, extensions and more. I won’t go through all of them here, but the CRUDS, conditional constructors, paging queries, and custom primary key policies described above are basically enough for daily development.
Of course, if you think you can not use enough, but also want to understand the framework of the source code implementation, that is no problem. In the next article, I’ll talk about source code analysis of frameworks, so stay tuned,
Thank you very much for reading and I hope this article has been helpful and enlightening to you.
The article continues to update, wechat search “Java technology enthusiasts”, the first time after paying attention to the technical article push, article classification is collected on github: github.com/yehongzhi, you can always find what you are interested in
Please give me a thumbs-up if you think it is useful. Your thumbs-up is the biggest motivation for my creation
I’m a programmer who tries to be remembered. See you next time!!
Ability is limited, if there is any mistake or improper place, please criticize and correct, study together!