将 Javers 自动审计集成到 JPA/Hibernate 实体管理器,无需 spring 框架 (Vanilla Javers)

发布于 2025-01-14 23:16:08 字数 2107 浏览 4 评论 0原文

我目前正在开发一个带有 REST 服务的 Java 项目,用于存储在带有 mysql 数据库的 Wildfly 应用程序服务器上使用 jarkarta、hibernate 运行的数据。为了存储数据,我准备了一个资源,DAO 可以持久保存实体:

服务:

@Path("/users")
public class UserService extends BasicWebServiceOperation {

    @Inject
    private UserDao repo;

    @POST
    @Produces("application/json")
    @UserRoles(values = {UserRole.ADMIN})
    public Response createOrUpdateUser(UserDTO dto) {
        ModelMapper modelMapper = new ModelMapper();
        User newusr = modelMapper.map(dto, User.class);

        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<User>> constraintViolations = validator.validate(newusr);

        if (!constraintViolations.isEmpty()) {
            response.setResponseToError(newusr, "INVALID_USER", "User with constraint violations");
        }

        try {
            repo.persist(newusr);
        } catch (PersistenceException e) {
            response.setResponseToError(newusr, "Error", "Could not update or create user");
        }

        return createAndSendResponse();
    }
}

DAO:

public abstract class BasicDao<T> {

    @PersistenceContext
    protected EntityManager em;
    protected Class<T> inferredClass;

    public BasicDao() {

    }
    public BasicDao(Class<T> inferredClass) {
        this.inferredClass = inferredClass;
    }

    @JaversAuditable
    public void persist(T entity) {
        if(em.contains(entity)) {
            em.merge(entity);
        } else {
            em.persist(entity);
        }
    }

    @JaversAuditable
    public void delete(T entity) {
        em.remove(entity);
    }
}

到目前为止,保存数据是有效的。现在我想回顾一下为什么我决定选择 Javers。我已经看到了 自动审核方面 这对于我的 dao 所以我设置了 @JaversAuditable 因为我不使用任何 spring 框架库。

到目前为止,我已经尝试创建一个初始化 javers 的简单类。但我不知道这是如何自动注册的。剩下的唯一方法是,在 .persist() 之后我只是调用 javers.commit 但看起来不太好。有什么方法可以解决我的问题吗?

I am currently working on a Java project with a REST service to store data which run with jarkarta, hibernate on a wildfly application server with a mysql db. To store the data I prepare a resource that a DAO to persist entities:

Service:

@Path("/users")
public class UserService extends BasicWebServiceOperation {

    @Inject
    private UserDao repo;

    @POST
    @Produces("application/json")
    @UserRoles(values = {UserRole.ADMIN})
    public Response createOrUpdateUser(UserDTO dto) {
        ModelMapper modelMapper = new ModelMapper();
        User newusr = modelMapper.map(dto, User.class);

        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<User>> constraintViolations = validator.validate(newusr);

        if (!constraintViolations.isEmpty()) {
            response.setResponseToError(newusr, "INVALID_USER", "User with constraint violations");
        }

        try {
            repo.persist(newusr);
        } catch (PersistenceException e) {
            response.setResponseToError(newusr, "Error", "Could not update or create user");
        }

        return createAndSendResponse();
    }
}

DAO:

public abstract class BasicDao<T> {

    @PersistenceContext
    protected EntityManager em;
    protected Class<T> inferredClass;

    public BasicDao() {

    }
    public BasicDao(Class<T> inferredClass) {
        this.inferredClass = inferredClass;
    }

    @JaversAuditable
    public void persist(T entity) {
        if(em.contains(entity)) {
            em.merge(entity);
        } else {
            em.persist(entity);
        }
    }

    @JaversAuditable
    public void delete(T entity) {
        em.remove(entity);
    }
}

So far saving data works. Now i would like to audit every change why i decided me for javers. I have seen the auto-audit aspects which would be perfect for my dao so i set the @JaversAuditable because i dont use any spring framework libraries.

So far I have tried to create a simple class that initializes javers. However I don't know how this is then automatically registered. The only way left ist, that after the .persist() i just calling javers.commit but not looks nice. Are there any ways how i can solve it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦年海沫深 2025-01-21 23:16:08

@JaversAuditable属于Spring AOP,在非spring内部不可见
项目,但在非spring项目中,可以使用javax.interceptor编写自定义的注解来审计
自动您的实体。像这样的事情:

import javax.interceptor.InterceptorBinding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@InterceptorBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface JaversAuditable {
}

您需要将 persist 方法的返回类型从 void 更改为 Object 并返回您的实体,因为 javers 在 commit 方法中需要这样做。

@Interceptor
@JaversAuditable
public class JaversAuditableInterceptor {

    @Inject
    private JaversConfig javersConfig;


    @AroundInvoke
    public Object auditEntities(InvocationContext context) {
        try {

            //distinguishing the name of the method on which the interceptor is called
            String methodName = context.getMethod().getName();
            Object responseEntity = context.proceed();

            //auditing the result of persist method
            if (methodName.equals("persist")) {
                Javers javers = javersConfig.getJavers();
                Iterable<Object> list = this.collectReturnedObjects(responseEntity);
                for (Object o : list) javers.commit("myUser", o);
            }

            return responseEntity;

        } catch (Exception e) {
             throw new MyException();
        }
    }

    public Iterable<Object> collectReturnedObjects(Object returnedObject) {
        if (returnedObject instanceof Iterable) {
            return (Iterable) returnedObject;
        }

        return Lists.immutableListOf(returnedObject);
    }
}

这会审核 persist 方法内的更改。为审核
删除方法内部发生变化,您应该向其中添加另一个块
您的删除方法的拦截器。

@JaversAuditable belongs to Spring AOP, and is not visible inside non-spring
projects, but in a non-spring project, you can use javax.interceptor to write a customized annotation to audit
your entities automatically. Something like this:

import javax.interceptor.InterceptorBinding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@InterceptorBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface JaversAuditable {
}

You need to change the return type of your persist method from void to Object and return your entity, as this is needed by javers in the commit method.

@Interceptor
@JaversAuditable
public class JaversAuditableInterceptor {

    @Inject
    private JaversConfig javersConfig;


    @AroundInvoke
    public Object auditEntities(InvocationContext context) {
        try {

            //distinguishing the name of the method on which the interceptor is called
            String methodName = context.getMethod().getName();
            Object responseEntity = context.proceed();

            //auditing the result of persist method
            if (methodName.equals("persist")) {
                Javers javers = javersConfig.getJavers();
                Iterable<Object> list = this.collectReturnedObjects(responseEntity);
                for (Object o : list) javers.commit("myUser", o);
            }

            return responseEntity;

        } catch (Exception e) {
             throw new MyException();
        }
    }

    public Iterable<Object> collectReturnedObjects(Object returnedObject) {
        if (returnedObject instanceof Iterable) {
            return (Iterable) returnedObject;
        }

        return Lists.immutableListOf(returnedObject);
    }
}

This audits the changes inside the persist method. For auditing the
changes inside delete method you should add another block to this
interceptor for your delete method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文