spring-data-jpa-guide icon indicating copy to clipboard operation
spring-data-jpa-guide copied to clipboard

利用AuditingEntityListener在insert之前把请求header里面的租户ID和工作空间更新到通用字段里面

Open zhangzhenhuajack opened this issue 1 year ago • 1 comments

  1. 新增自己的AuditingEntityListener
package com.mega.workflow.suite.common;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.auditing.AuditingHandler;
import org.springframework.data.domain.Auditable;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import java.util.Optional;

import static com.mega.workflow.suite.common.Constant.HEADER_TENANT_ID;
import static com.mega.workflow.suite.common.Constant.WORKSPACE_CODE_HEADER;

@Component
public class MegaAuditingEntityListener{
    @Autowired
    private ObjectFactory<AuditingHandler> handler;

    /**
     * Sets modification and creation date and auditor on the target object in case it implements {@link Auditable} on
     * persist events.
     *
     * @param target
     */
    @PrePersist
    public void touchForPreCreate(Object target) {

        Assert.notNull(target, "Entity must not be null!");

        if (handler != null) {

            AuditingHandler object = handler.getObject();
            if (object != null) {
                object.markCreated(target);
            }

            if (target instanceof BaseEntity) {
                //更新工作空间到基础字段里面
                String workspaceCode = Optional.ofNullable(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader(WORKSPACE_CODE_HEADER)).orElse("molclone");
                BaseEntity baseEntity = (BaseEntity) target;
                baseEntity.setWorkspaceCode(workspaceCode);

                //更新租户ID到基础字段里面
                String tenantId = Optional.ofNullable(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader(HEADER_TENANT_ID)).orElse("-1");
                baseEntity.setTenantId(tenantId);
            }
        }
    }
    /**
     * Sets modification and creation date and auditor on the target object in case it implements {@link Auditable} on
     * update events.
     *
     * @param target
     */
    @PreUpdate
    public void touchForUpdate(Object target) {

        Assert.notNull(target, "Entity must not be null!");

        if (handler != null) {

            AuditingHandler object = handler.getObject();
            if (object != null) {
                object.markModified(target);
            }
        }
    }
}

  1. BaseEntity的内容如下:
package com.mega.workflow.suite.common;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;

import javax.persistence.*;
import javax.validation.constraints.Min;
import java.time.Instant;

@Data
@MappedSuperclass
@EntityListeners({MegaAuditingEntityListener.class})
@SuperBuilder(toBuilder = true)
@AllArgsConstructor
@NoArgsConstructor
public abstract class BaseEntity<T extends BaseEntity> {
	@Id
	@GeneratedValue(strategy= GenerationType.IDENTITY)
//	@GenericGenerator(name = "snowFlakeIdGenerator", strategy = "com.mega.workflow.suite.common.SnowFlakeIdGenerator")
//	@GeneratedValue(generator = "snowFlakeIdGenerator")
	@Comment("主键")
	@Column(name = "id", nullable = false)
	@Min(value = 1, message = "主键必须大于0")
	@ApiModelProperty("主键")
	private Long id;

	@Comment("创建者")
	@CreatedBy
	@Convert(disableConversion = true)
	@Column(name = "created_by")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@ApiModelProperty("创建者")
	private Long createdBy;

	@Transient
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	private String createdByUserName;

	@Comment("创建时间")
	@CreatedDate
	@Column(name = "created_date")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@ApiModelProperty("创建时间")
	private Instant createdDate;

	@Comment("更新者")
	@LastModifiedBy
	@Convert(disableConversion = true)
	@Column(name = "last_modified_by")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@ApiModelProperty("更新者")
	private Long lastModifiedBy;

	@Comment("更新时间")
	@LastModifiedDate
	@Column(name = "last_modified_date")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@ApiModelProperty("更新时间")
	private Instant lastModifiedDate;

	@Comment("乐观锁")
	@Version
	@Column(name = "version")
	@ApiModelProperty("乐观锁")
	private Integer version;

	@Comment("租户ID")
	@Convert(disableConversion = true)
	@Column(name = "tenant_id")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@ApiModelProperty("租户ID")
	private String tenantId;

	@Comment("逻辑删除")
	@Column(name = "deleted")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@ApiModelProperty("逻辑删除")
	private Boolean deleted;

	@Comment("删除时间")
	@Column(name = "deleted_date")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@ApiModelProperty("删除时间")
	private Instant deletedDate;

	@Comment("工作空间")
	@Convert(disableConversion = true)
	@Column(name = "workspace_code")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@ApiModelProperty("工作空间")
	private String workspaceCode;

	@PrePersist
	public void prePersist() {
		if (this.id == null || this.id <= 0) {
			this.deleted = false;
			this.deletedDate = Instant.parse("1999-09-02T00:00:00Z");
		}
	}

	@Transient
	public String getCreatedByUserName() {
		if (createdByUserName == null) {
			return "admin";
		}
		return createdByUserName;
	}

	@Transient
	@JsonIgnore
	public abstract T getUpdateEntity(T entity);
}

既BaseEntity里面引用@EntityListeners({MegaAuditingEntityListener.class}) 即可;

zhangzhenhuajack avatar Jan 21 '24 09:01 zhangzhenhuajack

参考:https://www.baeldung.com/jpa-entity-lifecycle-events

zhangzhenhuajack avatar Jan 21 '24 09:01 zhangzhenhuajack