SoFunction
Updated on 2025-04-11

How to solve the problem of common field filling in SpringBoot custom annotations

1.1 Problem Analysis

existNew employeesorAdded dish classificationWhen setting the creation time, create person, modify time, modify person and other fields,Editing the stafforEdit the dish categoryWhen setting fields such as modification time and person modification, you need to set.

These fields belong to public fields, that is, many tables in our system will have these fields, as follows:

Serial number Field name meaning Data Type
1 create_time Creation time datetime
2 create_user Created by id bigint
3 update_time Modification time datetime
4 update_user Modify person id bigint

For these fields, our assignment method is:

1). When adding new data, set createTime and updateTime to the current time, and createUser and updateUser to the current login user ID.

2). When updating data, set updateTime to the current time and updateUser to the current login user ID.

Currently, in our project, these fields are processed in each business method to perform assignment operations, as follows:

New employee methods:

	/**
      * New employees
      *
      * @param employeeDTO
      */
    public void save(EmployeeDTO employeeDTO) {
        //.......................
		//
        //Set the creation time and modification time of the current record        (());
        (());

        //Set the current record id and modify the id        (());//Currently write fake data and modify it later        (());
		///
        (employee);
    }

How to edit the employee:

	/**
      * Edit employee information
      *
      * @param employeeDTO
      */
    public void update(EmployeeDTO employeeDTO) {
       //........................................
	   ///
        (());
        (());
       ///

        (employee);
    }

New dish classification method:

	/**
      * Added categories
      * @param categoryDTO
      */
    public void save(CategoryDTO categoryDTO) {
       //....................................
       //
        //Set creation time, modification time, creation person, modification person        (());
        (());
        (());
        (());
        ///

        (category);
    }

Modify the dish classification method:

	/**
      * Modify the classification
      * @param categoryDTO
      */
    public void update(CategoryDTO categoryDTO) {
        //....................................
        
		//
        //Set the modification time and modify the person        (());
        (());
        //

        (category);
    }

If these public fields are processed in accordance with the above operation methods, they need to operate in each business method, and the encoding is relatively redundant and cumbersome. Can these public fields be processed uniformly in a certain place to simplify development?

The answer is yes. We use AOP facet programming to achieve functional enhancement to complete the automatic filling function of public fields.

1.2 Implementation ideas

When implementing automatic filling of common fields, that is, assigning specified values ​​to the specified fields when inserting or updating, the advantage of using them is that these fields can be processed uniformly, avoiding duplicate code.

In the above problem analysis, we mentioned that there are four public fields that need to be assigned in new/update. The specific situation is as follows:

Serial number Field name meaning Data Type Operation Type
1 create_time Creation time datetime insert
2 create_user Created by id bigint insert
3 update_time Modification time datetime insert、update
4 update_user Modify person id bigint insert、update

Implementation steps:

1). Custom annotation AutoFill, used to identify methods that require automatic filling of common fields

2). Customize the section class AutoFillAspect, and adds AutoFill annotation method to uniformly intercept, assign values ​​to public fields through reflection.

3). Add AutoFill annotation to the Mapper method

To achieve the above steps, you need to master the following knowledge (I have learned all the course contents before)

**Technical points: **Enum, annotation, AOP, reflection

1.3 Code Development

According to the implementation steps analyzed in the previous section, the total of three steps is implemented.

1.3.1 Step 1

Custom annotations AutoFill

Enter the sky-server module and create a package.

package ;

import ;
import ;
import ;
import ;
import ;

/**
  * Custom annotations used to identify a method that requires automatic filling of function fields
  */
@Target()
@Retention()
public @interface AutoFill {
    //Database operation type: UPDATE INSERT    OperationType value();
}

Among them, OperationType has been defined in the sky-common module

package ;

/**
  * Database operation type
  */
public enum OperationType {

    /**
      * Update operation
      */
    UPDATE,

    /**
      * Insert operation
      */
    INSERT
}

1.3.2 Step 2

Custom facets AutoFillAspect

In the sky-server module, create a package.

package ;

/**
  * Customize the section to realize the automatic filling processing logic of common fields
  */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
      * Point of entry
      */
    @Pointcut("execution(* .*.*(..)) && @annotation()")
    public void autoFillPointCut(){}

    /**
      * Pre-notification, assign public fields in the notification
      */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        /important
        //You can debug first to see if you can enter this method? Add AutoFill annotation in the mapper method in advance.        ("Start the public field autofill...");

    }
}

Improve the autoFill method of custom sections AutoFillAspect

package ;

import ;
import ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

/**
  * Customize the section to realize the automatic filling processing logic of common fields
  */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
      * Point of entry
      */
    @Pointcut("execution(* .*.*(..)) && @annotation()")
    public void autoFillPointCut(){}

    /**
      * Pre-notification, assign public fields in the notification
      */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        ("Start the public field autofill...");

        //Get the database operation type on the currently intercepted method        MethodSignature signature = (MethodSignature) ();//Method Signature Object        AutoFill autoFill = ().getAnnotation();//Get the annotation object on the method        OperationType operationType = ();//Get database operation type
        //Get the parameters of the currently intercepted method--entity object        Object[] args = ();
        if(args == null ||  == 0){
            return;
        }

        Object entity = args[0];

        //Prepare the assigned data        LocalDateTime now = ();
        Long currentId = ();

        //Depend on the current different operation types, the corresponding attributes are assigned through reflection to the corresponding attributes        if(operationType == ){
            // Assign values ​​to 4 public fields            try {
                Method setCreateTime = ().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, );
                Method setCreateUser = ().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, );
                Method setUpdateTime = ().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, );
                Method setUpdateUser = ().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, );

                // Assign value to object attributes through reflection                (entity,now);
                (entity,currentId);
                (entity,now);
                (entity,currentId);
            } catch (Exception e) {
                ();
            }
        }else if(operationType == ){
            // Assign values ​​to 2 public fields            try {
                Method setUpdateTime = ().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, );
                Method setUpdateUser = ().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, );

                // Assign value to object attributes through reflection                (entity,now);
                (entity,currentId);
            } catch (Exception e) {
                ();
            }
        }
    }
}

1.3.3 Step 3

Add AutoFill annotation to the Mapper interface method

byCategoryMapperAs an example, adding @AutoFill() annotation to the new and modified methods is also requiredEmployeeMapperDo the same

package ;

@Mapper
public interface CategoryMapper {
    /**
      * Insert data
      * @param category
      */
    @Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, update_user)" +
            " VALUES" +
            " (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
    @AutoFill(value = )
    void insert(Category category);
    /**
      * Modify the classification according to id
      * @param category
      */
    @AutoFill(value = )
    void update(Category category);

}

at the same time, comment out the code assigned by the business layer to the public field.

1). Code comments to assign public fields in new and editing methods for employee management.

2). Code comments to assign public fields in the new and modified methods of dish classification management.

Summarize

The above is personal experience. I hope you can give you a reference and I hope you can support me more.