Java framework learning (2) SSM system: Spring, SpringMVC, MybatisPlus

Spring

In the original layered architecture implementation, the Controller layer responsible for responding to requests depends on the Service layer for business logic processing, and the service layer for business logic processing depends on the Dao layer for data access. The upper and lower layers depend on each other for coupling, and the disadvantage of coupling is that it affects the whole body, which is not conducive to later maintenance and expansion.

For layered decoupling, Spring uses IoC control inversion and DI dependency injection to solve the coupling problem.
insert image description here

IoC Inversion of Control

The idea of ​​IoC (Inversion of Control) inversion of control: When using an object, it no longer actively creates an object with new, but converts it to an externally provided object. During this process, the control of object creation is transferred from the program to the outside.

  • Spring technology implements the idea of ​​IoC. Spring provides a container, called IoCa container, which is used to act as a container in the idea of ​​IoC.“外部”的概念
  • The IoC container is responsible for a series of tasks such as object creation and initialization, and the created or managed objects are collectively IoCreferred to in the container asBean

DI dependency injection

IoC inversion of control is equivalent to handing over the object to the container for management, which is the process from object to container, while DI (Dependency Dependency Injection) is the process of taking out the corresponding object from the container.

Bean

Bean basic configuration

name

The bean tag specifies the name attribute configuration alias:

insert image description here
insert image description here

scope

The scope attribute of the bean tag configures the scope of the bean. The default scope attribute value is singleton, and the bean object is a singleton. If you want to build a non-singleton object, specify the attribute value as prototype
insert image description here

Bean instantiation method

The essence of a bean is an object, and it can be constructed in the following four ways:

  • 1. Instantiate the bean through the no-argument construction method (the default construction method), so a class to be handed over to the IoC container, if the no-argument construction method does not exist, an exception will be thrown if you want to construct the beanBeanCreationException
  • 2. Use the static factory to instantiate the bean, first instantiate the static factory class, and then execute the production method whose attribute field of the factory method is the static factory.
  • 3. Instantiate the bean using the instance factory. First instantiate the instance factory class, and then specify factory-methodthe attributes and factory-beanattributes when instantiating the bean.
  • 4. The way of using FactoryBean. This method is essentially the same as method 3, except that spring provides us with interface specifications to make it more concise when writing bean configurations.

Use the factory method to instantiate to facilitate the expansion of the instantiation process

insert image description here

FactoryBean is an interface standard provided by Spring.
insert image description here

Bean life cycle

For Prototype Bean, when the user getBean obtains the instance of Prototype Bean, the IOC container will no longer manage the current instance, but hand over the management right to the user, and then getBean will generate a new instance.

So when we describe the life cycle of Bean, we all refer to Singleton Bean.

Bean life cycle process:

  • Step 1, instantiate a Bean object; construct
  • Step 2, set related properties and dependencies for Bean; propertiesSet
  • Step 3, initialization; init
  • Step 4, destroy; destroy

There are two ways to set the life cycle control method of the bean:
the first method: first provide the life cycle control method in the class, and then specify the init-method and destroy-method in the bean tag when configuring the bean.

insert image description here

The second way: by implementing the InitializingBean interface and DisposableBean interface provided by Spring:


The order of the life cycle:
insert image description here

From the above, you can see that the init method and destroy method on the bean tag have a larger scope than the implemented interface method (init first, then destroy).

Note: To see the effect of destroy, we need to manually close the IOC container.
The way to close the IOC container can be through close()the method of the container or through registerShutdownHook()the method of the container.

insert image description here

insert image description here

Dependency Injection

Provide a set() method or use a constructor.
insert image description here
Case 1: Use set dependency to inject a reference type.
insert image description here
Case 2: Use set to inject simple types
insert image description here
Case 3: Use constructor to inject simple types:

insert image description here

In the fourth case, use the constructor to inject the reference type:
insert image description here

insert image description here

Dependency autowiring

The bean tag is automatically assembled using the autowire attribute, and
insert image description here
the value of the autowire attribute can be selected as follows:
insert image description here

Mybatis-Plus

Mybatis-Plus is an enhancement tool for Mybatis. Based on Mybatis, only enhancements are made without changes. It is designed to simplify development and provide efficiency.

insert image description here

configuration

Add dependencies:

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>

Add the @MapperScan annotation to the Springboot startup class to scan the mapper package.

@SpringBootApplication
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MybatisplusApplication {
    
    
public static void main(String[] args) {
    
    
		SpringApplication.run(MybatisplusApplication.class, args);
	}
}

Configure log output in application.yml:

# 配置MyBatis日志
mybatis-plus:
	configuration:
		log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

BaseMapper

BaseMapper is the template mapper provided by Mybatis-Plus, which contains basic CRUD methods, and the generic type is the entity type of the operation.

Take the User entity as an example:

@Data //lombok注解
public class User {
    
    
	private Long id;
	private String name;
	private Integer age;
	private String email;
}

When we write our own mapper, we can inherit this template mapper.

public interface UserMapper extends BaseMapper<User> {
    
    
}

increase:

@Test
public void testInsert(){
    
    
User user = new User(null, "张三", 23, "[email protected]");
//INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
int result = userMapper.insert(user);
System.out.println("受影响行数:"+result);
//1475754982694199298
System.out.println("id自动获取:"+user.getId());
}

delete:

@Test
public void testDeleteById(){
    
    
//通过id删除用户信息
//DELETE FROM user WHERE id=?
int result = userMapper.deleteById(1475754982694199298L);
System.out.println("受影响行数:"+result);

@Test
public void testDeleteBatchIds(){
    
    
//通过多个id批量删除
//DELETE FROM user WHERE id IN ( ? , ? , ? )
List<Long> idList = Arrays.asList(1L, 2L, 3L);
int result = userMapper.deleteBatchIds(idList);
System.out.println("受影响行数:"+result);
}
}

@Test
public void testDeleteByMap(){
    
    
//根据map集合中所设置的条件删除记录
//DELETE FROM user WHERE name = ? AND age = ?
Map<String, Object> map = new HashMap<>();
map.put("age", 23);
map.put("name", "张三");
int result = userMapper.deleteByMap(map);
System.out.println("受影响行数:"+result);
}

change:

@Test
public void testUpdateById(){
    
    
User user = new User(4L, "admin", 22, null);
//UPDATE user SET name=?, age=? WHERE id=?
int result = userMapper.updateById(user);
System.out.println("受影响行数:"+result);
}

check:

@Test
public void testSelectById(){
    
    
//根据id查询用户信息
//SELECT id,name,age,email FROM user WHERE id=?
User user = userMapper.selectById(4L);
System.out.println(user);
}

@Test
public void testSelectBatchIds(){
    
    
//根据多个id查询多个用户信息
//SELECT id,name,age,email FROM user WHERE id IN ( ? , ? )
List<Long> idList = Arrays.asList(4L, 5L);
List<User> list = userMapper.selectBatchIds(idList);
list.forEach(System.out::println);
}

@Test
public void testSelectByMap(){
    
    
//通过map条件查询用户信息
//SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
Map<String, Object> map = new HashMap<>();
map.put("age", 22);
map.put("name", "admin");
List<User> list = userMapper.selectByMap(map);
list.forEach(System.out::println);
}

@Test
public void testSelectList(){
    
    
//查询所有用户信息
//SELECT id,name,age,email FROM user
List<User> list = userMapper.selectList(null);
list.forEach(System.out::println);
}

General Service

Description:
General Service CRUD encapsulates IService interface,Further encapsulate CRUD Use get query single line remove delete list query set page pagination prefix naming method to distinguish Mapper layer to avoid confusion,
the generic type T is any entity object.
It is recommended that if there is a possibility of customizing the general Service method, please create your own IBaseService to inherit the
base class provided by Mybatis-Plus Official
website address: https://baomidou.com/pages/49cc81/#service- crud-%E6%8E%A5%E5%8F%
A3

Steps to use:
1. Create Service interface and implementation class.

/**
* UserService继承IService模板提供的基础功能
*/
public interface UserService extends IService<User> {
    
    
}

/**
* ServiceImpl实现了IService,提供了IService中基础功能的实现
* 若ServiceImpl无法满足业务需求,则可以使用自定的UserService定义方法,并在实现类中实现
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements
UserService {
    
    
}

Use cases:
1. Test the number of query records:

@Autowired
private UserService userService;
@Test
public void testGetCount(){
    
    
long count = userService.count();
System.out.println("总记录数:" + count);
}

2. Test batch insertion:

@Test
public void testSaveBatch(){
    
    
// SQL长度有限制,海量数据插入单条SQL无法实行,
// 因此MP将批量插入放在了通用Service中实现,而不是通用Mapper
ArrayList<User> users = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    
    
User user = new User();
user.setName("ybc" + i);
user.setAge(20 + i);
users.add(user);
}
//SQL:INSERT INTO t_user ( username, age ) VALUES ( ?, ? )
userService.saveBatch(users);
}

Common Notes

@TableName

When using MyBatis-Plus to implement basic CRUD, we did not specify the table to be operated, but
set the generic User when the Mapper interface inherited BaseMapper, and the operated table is the user table
. From this, it is concluded that MyBatis-Plus When determining the table to operate, it is determined by the generic type of BaseMapper, that is, the entity type
, and the table name of the default operation is consistent with the class name of the entity type

If the class name of the entity class type is inconsistent with the table name of the table to be operated, what problems will occur?

Rename the table user to t_user and test the query function, and an error will occur.

At this point we can use the @TableName annotation to specify the name of the table to be operated on:
insert image description here

You can also use global configuration:
In the process of development, we often encounter the above problems, that is, tables corresponding to entity classes have fixed prefixes, such as t_ or tbl_
At this time, you can use the global configuration provided by MyBatis-Plus , set the default prefix for the table name corresponding to the entity class, then there is
no need to identify the table corresponding to the entity class through @TableName on each entity class

Then you can use the configuration of mybatis-plus in application.yml:

mybatis-plus:
	configuration:
		# 配置MyBatis日志
		log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
	global-config:
		db-config:
			# 配置MyBatis-Plus操作表的默认前缀
			table-prefix: t_

@TableId

When MyBatis-Plus implements CRUD, id is used as the primary key column by default, and when inserting data, the id is generated based on the strategy of the snowflake algorithm by default.

If the primary key represented in the entity class and table is not id, but other fields, such as uid, you need to use the @TableId annotation to identify the primary key on the attribute represented by the primary key of the entity class:insert image description here

The value attribute of @TableId
If the attribute corresponding to the primary key in the entity class is id, and the field representing the primary key in the table is uid, at this time, if only the annotation @TableId is added to the attribute id, an exception Unknown
column 'id' in 'field list' will be thrown, that is MyBatis-Plus will still
use id as the primary key of the table, and the primary key in the table is the field uid.
At this time, you need to pass the value attribute of the @TableId annotation to specify the primary key field in the table, @TableId("uid") or
@TableId (value="uid")

The type attribute of @TableId
The type attribute is used to define the primary key strategy
insert image description here
to configure the global primary key strategy:

mybatis-plus:
	configuration:
		# 配置MyBatis日志
		log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
	db-config:
		# 配置MyBatis-Plus操作表的默认前缀
		table-prefix: t_
		# 配置MyBatis-Plus的主键策略
		id-type: auto

snowflake algorithm

It is necessary to choose a suitable method to cope with the growth of data scale, so as to cope with the gradually increasing access pressure and data volume. The expansion methods of the database mainly include: business sub-database, master-slave replication, and database sub-table.

  • Vertical table splitting
    Vertical table splitting is suitable for splitting some columns that are not commonly used and take up a lot of space in the table.
    For example, for the nickname and description fields in the previous schematic diagram, suppose we are a dating website. When users filter other users, they
    mainly use the two fields of age and sex for query, while the two fields of nickname and description are mainly used to display
    generally not used in business queries. The description itself is relatively long, so we can separate these two fields into another
    table, so that when querying age and sex, it can bring a certain performance improvement.
  • Horizontal table division
    Horizontal table division is suitable for tables with a particularly large number of rows. Some companies require table division if the number of rows in a single table exceeds 50 million. This number can be used as a reference,
    but it is not an absolute standard. The key is to look at the table access performance. For some more complex tables, it may be more than 10 million
    to divide the table; and for some simple tables, even if the stored data exceeds 100 million rows, it is not necessary to divide the table.
    Compared with vertical table partitioning, horizontal table partitioning will introduce more complexity, such as how to deal with the requirement of globally unique data id
    • Primary key auto-increment
      Taking the most common user ID as an example, it can be segmented according to the range of 1000000, 1 ~ 999999 is put in Table 1, 1000000 ~ 1999999 is put in Table 2, and so on. The disadvantage of this is that the distribution may be uneven. It is possible that a segment actually stores only 1 piece of data, while another
      segment actually stores 10 million pieces of data.
    • The modulus
      also takes the user ID as an example. If we plan 10 database tables from the beginning, we can simply use the value of user_id % 10 to indicate the database table number to which the data belongs. In the sub-table, the user whose ID is 10086 is placed in the sub-table numbered 6. The advantage of this method is that the table distribution is relatively uniform, but the disadvantage is that it is very troublesome to expand the new table, and all data needs to be redistributed.
    • Snowflake Algorithm
      Snowflake Algorithm is a distributed primary key generation algorithm released by Twitter, which can ensure the non-duplication of primary keys in different tables and the ordering of the same table.

Principle of Snowflake Algorithm:
insert image description here
insert image description here
Advantages of Snowflake Algorithm: Overall, they are sorted according to time increment, and there will be no ID collision in the entire distributed system, so the efficiency is high.

@TableField

When MyBatis-Plus executes SQL statements, it must ensure that the attribute names in the entity class
are consistent with the field names in the table.
If the attribute names in the entity class are inconsistent with the field names, what problems will occur?

Case 1:
If the attribute in the entity class uses the hump naming style, and the field attribute in the table uses the underscore naming style, for example, if the entity class attribute userName, the field user_name in the table, MyBatis-Plus will automatically convert the underscore naming style to camelCase The naming style is equivalent to configuring in MyBatis.

Case 2:
If the attributes in the entity class and the fields in the table do not satisfy the case 1, for example, the attribute of the entity class is name, and the field in the table is username, then you need to use @TableFile("username") to set the attribute on the attribute of the entity class The corresponding field name.

insert image description here

@TableLogic

  • Physical deletion: real deletion, the corresponding data is deleted from the database, and the deleted data cannot be queried afterwards
  • Logical deletion: False deletion, modify the status of the field representing whether it is deleted in the corresponding data to "deleted status", and then
    this data record can still be seen in the database
  • Usage scenario: data recovery is possible

Steps to implement logical deletion:
Step 1: Create a logical deletion status field in the database, and set the default value to 0

insert image description here
Step 2: Add the logical deletion attribute to the entity class and add the annotation @TableLogic

insert image description here

Step 3: Test To test
the delete function, the actual execution is to modify
the UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0
to test the query function, the logically deleted data will not be queried by default
SELECT id,username AS name,age, email,is_deleted FROM t_user WHERE is_deleted=0

Conditional constructors and common interfaces

Wrapper: conditionally constructed abstract class, the topmost parent class. Help us construct the conditions for adding, deleting, modifying and checking.
insert image description here

QueryWrapper

Example 1: Assembling query conditions:

@Test
public void test01(){
    
    
//查询用户名包含a,年龄在20到30之间,并且邮箱不为null的用户信息
//SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE
	is_deleted=0 AND (username LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
	QueryWrapper<User> queryWrapper = new QueryWrapper<>();
	queryWrapper.like("username", "a")
	.between("age", 20, 30)
	.isNotNull("email");
	List<User> list = userMapper.selectList(queryWrapper);
	list.forEach(System.out::println);
}

Example 2: Assembling a sort condition

UpdateWrapper

plug-in

MyBatis Plus has its own paging plug-in, which can realize the paging function with simple configuration.

Steps to use:
1. Add configuration class

@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper") //可以将主类中的注解移到此处
public class MybatisPlusConfig {
    
    
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    
    
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
		interceptor.addInnerInterceptor(new
		PaginationInnerInterceptor(DbType.MYSQL));
		return interceptor;
	}
}

2. Test

@Test
public void testPage(){
    
    
//设置分页参数
Page<User> page = new Page<>(1, 5);
userMapper.selectPage(page, null);
//获取分页数据
List<User> list = page.getRecords();
list.forEach(System.out::println);
System.out.println("当前页:"+page.getCurrent());
System.out.println("每页显示的条数:"+page.getSize());
System.out.println("总记录数:"+page.getTotal());
System.out.println("总页数:"+page.getPages());
System.out.println("是否有上一页:"+page.hasPrevious());
System.out.println("是否有下一页:"+page.hasNext());
}

Guess you like

Origin blog.csdn.net/baiduwaimai/article/details/131433105