在springbootapi中使用jpa和spaghetti代码的java选项

nnvyjq4y  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(311)

我有一些关于在我正在开发的api中使用optionals的问题。
首先,我在本机查询(在jpa存储库中)中使用return选项。这样用可以吗?
我还有一个服务,它检查我的一个实体是否通过它的id退出,如果不是,它抛出一个自定义异常。我不明白的是服务可以返回对象类型,但是jpa查询定义是:optional findbyid(id)???

public BasicTvShowInfo getBasicTvShowInfoById (Integer idTvShow) throws ResourceNotFoundException {
        return basicTvShowInfoRepository.findById(idTvShow).orElseThrow(() -> new ResourceNotFoundException(
                "The tv show with the id : " + idTvShow + " was not found."));
    }

最后,当我想发布实体调用tvshowreminder时,我有一个验证。该实体声明为:

@Entity
@Table(name = "tv_show_reminder")
public class TvShowReminder {

    // Attributes
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column (name = "id_tv_show_reminder")
    private Integer idTvShowReminder;

    @ManyToOne(optional = false)
    @JoinColumn(name="id_user")
    @NotNull(message = "Provide user {idUser}")
    private User user;

    @ManyToOne()
    @JoinColumn(name= "id_basic_tv_show_info")
    private BasicTvShowInfo basicTvShowInfo;

    @ManyToOne()
    @JoinColumn(name= "id_tv_show_created_by_user")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private UserTvShow userTvShow;

    private Boolean completed;

    @Column(name = "current_season")
    private Integer currentSeason;

    @Column(name = "current_episode")
    private Integer currentEpisode;

    @Column(name = "personal_rating")
    private Integer personalRating;

它有两个嵌套实体,可以为空。基本的vshowinfo和usertvshow。

@Entity
@Table(name = "basic_tv_show_info")

public class BasicTvShowInfo {

    @Id
    @Column(name = "id_basic_tv_show_info")
    @NotNull(message = "Provide id (Integer)")
    private Integer id;

    @Column(name = "original_name")
    @JsonProperty("original_name")
    @NotNull(message = "Provide original_name (String)")
    private String originalName;
}

@Entity
@Table(name = "tv_show_created_by_user")
public class UserTvShow {

    // Attributes
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_tv_show_created_by_user")
    private Integer idTvShowCreatedByUser;

    @ManyToOne()
    @JoinColumn(name= "id_user")
    @NotNull(message = "Provide user {idUser}")
    private User user;

    @Column(name = "name_tv_show")
    @NotNull(message = "Provide nameTvShow (String)")
    private String nameTvShow;

    private String genre;

    @Column(name = "production_company")
    private String productionCompany;
}

我在服务中有一个验证方法,用于检查:
如果basictvshowinfo和usertvshow都为空。
如果两个对象(basictvshowinfo和usertvshow)都有一个id。
如果登录的用户已经有一个提供了basictvshowinfo id的提醒。
如果登录的用户已经有一个带有usertvshow id的提醒。
在所有这些情况下,我抛出异常。
我如何重构这个工作完美但我想写得更优雅的服务方法?我真的不喜欢用那么多if elseif else和嵌套if。很难遵循规则。
方法如下:

private void validateExistenceOfTvShowReminder(TvShowReminder tvShowReminder) throws ResourceAlreadyExistsException, BusinessLogicValidationFailure, ResourceNotFoundException {
        Optional<TvShowReminder> tvShowReminderOptional = Optional.empty();
        String messageError = null;

        // If both the basic tv show info object and user tv show object ARE PRESENT -> exception
        // If the basic tv show info object id already exists in the reminders table -> exception
        // If the user tv show info object id already exists in the reminders table -> exception
        // If both are null -> exception.

        if(tvShowReminder.getBasicTvShowInfo() != null && tvShowReminder.getUserTvShow() != null){

            if(tvShowReminder.getBasicTvShowInfo().getId() != null && tvShowReminder.getUserTvShow().getIdTvShowCreatedByUser() != null)
                throw new BusinessLogicValidationFailure("You cant have a reminder that point to a tv show from the system and to a tv show created by the user");

        } else if(tvShowReminder.getBasicTvShowInfo() != null){

            if(tvShowReminder.getBasicTvShowInfo().getId() != null) {
                tvShowReminderOptional = tvShowReminderRepository.findByUserIdAndTvShowId(tvShowReminder.getUser().getIdUser(), tvShowReminder.getBasicTvShowInfo().getId());
                messageError = "User already created a tv show reminder with the basicTvShowInfo id : " + tvShowReminder.getBasicTvShowInfo().getId();
            }

        } else if (tvShowReminder.getUserTvShow() != null){

            if(tvShowReminder.getUserTvShow().getIdTvShowCreatedByUser() != null) {

                // Validate if the user tv show of the reminder actually belongs to the logged user.
                if(Optional.ofNullable(userTvShowService.getUserTvShow(tvShowReminder.getUser().getIdUser(), tvShowReminder.getUserTvShow().getIdTvShowCreatedByUser())).isPresent()) {

                    tvShowReminderOptional = tvShowReminderRepository.findByUserIdAndTvShowCreatedByUserId(tvShowReminder.getUser().getIdUser(), tvShowReminder.getUserTvShow().getIdTvShowCreatedByUser());
                    messageError = "User already created a tv show reminder with a userTvShow id : " + tvShowReminder.getUserTvShow().getIdTvShowCreatedByUser();
                }
            }

        } else {
            messageError = "To create a tv show reminder you have to provided a basicTvShowInfo id OR a userTvShow id";
            throw new BusinessLogicValidationFailure(messageError);
        }

        // Each query findByUserIdAndTvShowId and findByUserIdAndTvShowCreatedByUserId return an optional with the tv show or an empty optional.
        // This method will return true if there is a tv show present in the optional OR returns false if is an empty optional (with null value).
        if(tvShowReminderOptional.isPresent()){
            throw new ResourceAlreadyExistsException(messageError);
        }
    }

// Repository if it is of any help is:

@Repository
public interface TvShowReminderRepository extends JpaRepository<TvShowReminder, Integer> {
    Page<TvShowReminder> findByUser_IdUser(Pageable pageable, Integer idUser);
    List<TvShowReminder> findByUser_IdUser(Integer idUser);

    @Query(value = "SELECT * FROM tv_show_reminder WHERE id_user = ?1 and id_basic_tv_show_info = ?2", nativeQuery = true)
    Optional<TvShowReminder> findByUserIdAndTvShowId(Integer idUser, Integer idBasicTvShowInfo);

    @Query(value = "SELECT * FROM tv_show_reminder WHERE id_user = ?1 and id_tv_show_created_by_user = ?2", nativeQuery = true)
    Optional<TvShowReminder> findByUserIdAndTvShowCreatedByUserId(Integer idUser, Integer idTvShowCreatedByUser);

    @Query(value = "SELECT * FROM tv_show_reminder WHERE id_user = ?1 and id_tv_show_reminder = ?2", nativeQuery = true)
    Optional<TvShowReminder> findByIdTvShowReminderAndUserId(Integer idUser, Integer idTvShowReminder);
}

抱歉发了这么长的帖子,提前谢谢你,如果有人能帮我或者指导我正确的做法我会很感激的。

y0u0uwnf

y0u0uwnf1#

首先,我在本机查询(在jpa存储库中)中使用return选项。这样用可以吗?
我不明白为什么会不好。
我还有一个服务,它检查我的一个实体是否通过它的id退出,如果不是,它抛出一个自定义异常。我不明白的是服务可以返回对象类型,但是jpa查询定义是:optional findbyid(id)???
这也很好。spring数据只是不想在每次找不到对象时抛出异常,这就是为什么他们使用可选方法的原因。你可以用它做任何你想做的事。
最后,当我想发布实体调用tvshowreminder时,我有一个验证。该实体声明为:
要将验证重构为更可读的形式,我建议您研究jakarta/java ee验证api,也称为bean验证api:https://www.baeldung.com/javax-validation

相关问题