Как обрабатывать NullPointer в проекциях Spring Data JPA

#java #hibernate #spring-data-jpa

#java #переход в спящий режим #spring-data-jpa

Вопрос:

Есть какие-либо мысли, есть ли способ создать пользовательский метод для обработки null или любых других исключений, возникающих при создании проекции?

В приведенном ниже запросе JPQL я пытаюсь создать пользовательский объект, но когда в столбце UpdatedBy нет данных (в базе данных это null), тогда происходит внутренний сбой, поскольку невозможно продолжить работу с нулевым объектом дальше (getUpdatedBy -> getProfile -> getName).

 @Query("select new john.home.com.demo.repository.projections.AgreementType(agreement.name, "  
        "agreement.type, "  
        "agreement.audit.createdBy.profile.name, "  
        "agreement.audit.updateDate, "  
        "agreement.audit.updatedBy.profile.name) from Agreement agreement")
List<AgreementType> findAgreementTypes();
  

Вот мои объекты:

Соглашение:

 @Setter
@Getter
@NoArgsConstructor
@Entity
@Table(name = "AGREEMENT")
public class Agreement {
    @Id
    @Column(name = "AGREEMENT_ID")
    private Long id;

    @Column(name = "NAME")
    private String name;

    @Column(name = "TYPE")
    private String type;

    @Embedded
    Audit audit;
  

Встраиваемый аудит

 @Getter
@Setter
@Embeddable
public class Audit {
    @OneToOne
    @JoinColumn(name = "CREATED_BY")
    private SystemProcess createdBy;

    @Column(name = "CREATION_DATE")
    private LocalDate creationDate;

    @Column(name = "UPDATE_DATE")
    private LocalDate updateDate;

    @OneToOne
    @JoinColumn(name = "UPDATED_BY")
    private SystemProcess updatedBy;
  

Системный процесс:

 @Getter
@Setter
@Entity
@Table(name = "sys_process")
public class SystemProcess {
    @Id
    @Column(name = "PROCESS_ID")
    private Integer id;

    @Column(name = "PROCESS_MSG_TXT")
    private String messageText;

    @OneToOne
    @JoinColumn(name = "PROFILE_ID")
    private SystemProfile profile;
  

SystemProfile:

 @Getter
@Setter
@Entity
@Table(name = "sys_profile")
public class SystemProfile {
    @Id
    @Column(name = "PROFILE_ID")
    private Integer id;

    @Column(name = "PROFILE_NM")
    private String name;
}
  

Вот запрос JPQL, который я использовал, однако он не работает по неизвестной причине

 @Query("select new dan.home.pl.demo.repository.projections.AgreementType("  
            "agreement.name, "  
            "agreement.audit.createdBy.profile.name, "  
            "case when (agreement.audit.updatedBy is null) then 'Dummy Name' else agreement.audit.updatedBy.profile.name end"  
            ") from Agreement agreement")
    List<AgreementType> findAgreementTypes();
  

Ответ №1:

Вы можете использовать оператор case для достижения этой цели, ознакомьтесь с документацией здесьhttps://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch11.html

Что-то вроде

 case when agreement.audit is not null then agreement.audit.updatedBy.profile.name end
  

Комментарии:

1. К сожалению, это работает, но не так, как я ожидал. Он способен изменять записи в зависимости от случая (что-то вроде if a, затем 1 else 2), но чего я пытаюсь достичь: если объекта нет (что означает null) — поместите фиктивную строку, в противном случае извлеките строку. Пожалуйста, взгляните на описание, я добавил запрос, который я использовал, может быть, у вас была такая проблема

2. @DanilTk Проверьте примеры в Hibernate документации 15.35. Искомые регистровые выражения

3. Да, даже это возможно. Синтаксис доступен в документации, которой поделился @MartinBG. СЛУЧАЙ {операнд}, КОГДА {test_value} ЗАТЕМ {match_result}, ИНАЧЕ {miss_result} ЗАКАНЧИВАЕТСЯ