Изменить сущность Hibernate onSave - PullRequest
1 голос
/ 02 марта 2020

Зарегистрированный пользователь создает проект. Я хотел бы обновить поле createBy в ProjectModel, прежде чем сохранять его в БД.

@Entity
@Table(name = "PROJECTS")
@Inheritance(strategy = InheritanceType.JOINED)
public @Data class ProjectModel extends BaseModel {

    @Length(min = 4, max = 30)
    @NotNull
    private String name;

    @NotNull
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "USER_ID")
    private User createdBy;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "PROJECT_ID")
    private List<RinexFileModel> rinexFileModels;

    @Enumerated(EnumType.STRING)
    private Status status = Status.NEW;

    public void addRinexFiles(List<RinexFileModel> rinexFiles) {
        this.rinexFileModels.addAll(rinexFiles);
    }

    public void addRinexFile(RinexFileModel rinexFile) {
        this.rinexFileModels.add(rinexFile);
    }

    public enum Status {
        NEW, READY, PROCESSING, PROCESSED
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}

Для этого есть как минимум два варианта.

  • Методами обратного вызова ( @ PrePersist , et c.) Аналогично приведенному ниже коду, но мне нужна UserModel и доступ к пружинному компоненту

    похож на этот SpringContext пример

enter image description here Этот подход, который мне не нравится из-за принципа единой ответственности, был нарушен, я думаю ит.

  • Перехватчик (EmptyInterceptor)

    enter code here

HibernateInterceptorImpl Interceptor

public class HibernateInterceptorImpl extends EmptyInterceptor {

    @Resource
    private HibernateInterceptorStrategy hibernateInterceptorStrategy;

    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
        boolean entityChanged = false;

        final EmptyInterceptor interceptor = hibernateInterceptorStrategy.getStrategy(entity);

        if (nonNull(interceptor)) {
            entityChanged = interceptor.onSave(entity, id, state, propertyNames, types);
        }

        return entityChanged;
    }
}

@Component("hibernateInterceptorStrategy")
public class HibernateInterceptorStrategy {

    @Resource
    private Map<Class, EmptyInterceptor> hibernateInterceptorStrategies;

    public EmptyInterceptor getStrategy(Object object) {
        for (Class clazz : hibernateInterceptorStrategies.keySet()) {
            if (object.getClass() == clazz) {
                return hibernateInterceptorStrategies.get(clazz);
            }
        }
        return null;
    }
}

Реализация ProjectInterceptor

public class ProjectInterceptorImpl extends EmptyInterceptor {

    @Resource
    private SessionService sessionService;

    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
        final ProjectModel project = (ProjectModel) entity;

        if (isNull(project.getCreatedBy())) {
            project.setCreatedBy(sessionService.getCurrentUser());
        }

        return true;
    }
}

Результаты отладки (пользователь успешно добавлен, но тем не менее исключение при проверке @NotNull для созданного Byy)

enter image description here

enter image description here

ИСПРАВЛЕНИЕ: также измените массив состояний. Но хорошего решения для этого нет.

enter image description here

1 Ответ

1 голос
/ 23 марта 2020

Для заполнения пользовательских данных перед сохранением модели можно использовать Spring Data @ CreateBy аннотация. Проверьте это статья первая

Пользователь + встроенный класс UserPrincipal был изменен только на UserPrincipal из-за пружинной безопасности, основанной на возвратах User Service UserPrincipal. Таким образом, для моего проекта нет ничего сложного в том, чтобы изменить его на модель одного пользователя

enter image description here

Включить аудит JPA enter image description here

Результат enter image description here

...