Quarkus Swagger UI Hibernate 对 PostgreDB 的删除请求默默失败

问题描述 投票:0回答:1

我有一个使用 PostgreSQL 和 SwaggerUI 的 Quarkus 项目,在该项目中我可以手动从 IntelliJ DB UI 中的表中删除行,但是当我尝试使用 DELETE 请求执行此操作时,它会失败,并且不会引发任何异常或错误代码。奇怪的是,如果我尝试删除的行没有通过任何 FK 连接到另一个表,则请求实际上会执行并删除该行。然而,即使有一些 FK,这也不应该成为问题,因为我可以手动完成。我还尝试使用 Postman 删除请求,并得到相同的结果 - 默默地失败。我将提供我的实体、服务、存储库和资源类。需要明确的是,GameEntity 中有 4 个 FK 字段,但我只会提供其中之一(流派),因为它们的行为都是相同的。我正在尝试从 Games 表中删除。

编辑:我查看了我的休眠日志,似乎它做了很多选择,但最后它没有执行删除。此外,如上所述,当实体与另一个实体没有连接时,它会被删除,并且可以在日志中看到删除子句。

删除没有连接的实体:

[Hibernate] 
    select
        de1_0.id,
        de1_0.developer,
        de1_0.email 
    from
        Developers de1_0
[Hibernate] 
    select
        g1_0.developerID,
        g1_0.id,
        g1_0.description,
        g1_0.genreID,
        g2_0.id,
        g2_0.genre,
        g1_0.platformID,
        p1_0.id,
        p1_0.platform,
        g1_0.publisherID,
        p2_0.id,
        p2_0.email,
        p2_0.publisher,
        g1_0.release_date,
        g1_0.title 
    from
        Games g1_0 
    left join
        Genres g2_0 
            on g2_0.id=g1_0.genreID 
    left join
        Platforms p1_0 
            on p1_0.id=g1_0.platformID 
    left join
        Publishers p2_0 
            on p2_0.id=g1_0.publisherID 
    where
        g1_0.developerID = any (?)
[Hibernate] 
    select
        de1_0.id,
        de1_0.developer,
        de1_0.email,
        g1_0.developerID,
        g1_0.id,
        g1_0.description,
        g1_0.genreID,
        g2_0.id,
        g2_0.genre,
        g1_0.platformID,
        p1_0.id,
        p1_0.platform,
        g1_0.publisherID,
        p2_0.id,
        p2_0.email,
        p2_0.publisher,
        g1_0.release_date,
        g1_0.title 
    from
        Developers de1_0 
    left join
        Games g1_0 
            on de1_0.id=g1_0.developerID 
    left join
        Genres g2_0 
            on g2_0.id=g1_0.genreID 
    left join
        Platforms p1_0 
            on p1_0.id=g1_0.platformID 
    left join
        Publishers p2_0 
            on p2_0.id=g1_0.publisherID 
    where
        de1_0.id=?
[Hibernate] 
    delete 
    from
        Developers 
    where
        id=?

删除具有连接的实体:

[Hibernate] 
    select
        ge1_0.id,
        ge1_0.description,
        ge1_0.developerID,
        d1_0.id,
        d1_0.developer,
        d1_0.email,
        ge1_0.genreID,
        g1_0.id,
        g1_0.genre,
        ge1_0.platformID,
        p1_0.id,
        p1_0.platform,
        ge1_0.publisherID,
        p2_0.id,
        p2_0.email,
        p2_0.publisher,
        ge1_0.release_date,
        ge1_0.title,
        r1_0.gameID,
        r1_0.id,
        r1_0.comment,
        r1_0.rating,
        r1_0.userID,
        u1_0.id,
        u1_0.email,
        u1_0.username 
    from
        Games ge1_0 
    join
        Developers d1_0 
            on d1_0.id=ge1_0.developerID 
    join
        Genres g1_0 
            on g1_0.id=ge1_0.genreID 
    join
        Platforms p1_0 
            on p1_0.id=ge1_0.platformID 
    join
        Publishers p2_0 
            on p2_0.id=ge1_0.publisherID 
    left join
        Reviews r1_0 
            on ge1_0.id=r1_0.gameID 
    left join
        Users u1_0 
            on u1_0.id=r1_0.userID 
    where
        ge1_0.id=?
[Hibernate] 
    select
        r1_0.userID,
        r1_0.id,
        r1_0.comment,
        r1_0.gameID,
        g1_0.id,
        g1_0.description,
        g1_0.developerID,
        d1_0.id,
        d1_0.developer,
        d1_0.email,
        g1_0.genreID,
        g2_0.id,
        g2_0.genre,
        g1_0.platformID,
        p1_0.id,
        p1_0.platform,
        g1_0.publisherID,
        p2_0.id,
        p2_0.email,
        p2_0.publisher,
        g1_0.release_date,
        g1_0.title,
        r1_0.rating 
    from
        Reviews r1_0 
    left join
        Games g1_0 
            on g1_0.id=r1_0.gameID 
    left join
        Developers d1_0 
            on d1_0.id=g1_0.developerID 
    left join
        Genres g2_0 
            on g2_0.id=g1_0.genreID 
    left join
        Platforms p1_0 
            on p1_0.id=g1_0.platformID 
    left join
        Publishers p2_0 
            on p2_0.id=g1_0.publisherID 
    where
        r1_0.userID=?
[Hibernate] 
    select
        g1_0.publisherID,
        g1_0.id,
        g1_0.description,
        g1_0.developerID,
        d1_0.id,
        d1_0.developer,
        d1_0.email,
        g1_0.genreID,
        g2_0.id,
        g2_0.genre,
        g1_0.platformID,
        p1_0.id,
        p1_0.platform,
        g1_0.release_date,
        g1_0.title 
    from
        Games g1_0 
    left join
        Developers d1_0 
            on d1_0.id=g1_0.developerID 
    left join
        Genres g2_0 
            on g2_0.id=g1_0.genreID 
    left join
        Platforms p1_0 
            on p1_0.id=g1_0.platformID 
    where
        g1_0.publisherID=?
[Hibernate] 
    select
        g1_0.platformID,
        g1_0.id,
        g1_0.description,
        g1_0.developerID,
        d1_0.id,
        d1_0.developer,
        d1_0.email,
        g1_0.genreID,
        g2_0.id,
        g2_0.genre,
        g1_0.publisherID,
        p2_0.id,
        p2_0.email,
        p2_0.publisher,
        g1_0.release_date,
        g1_0.title 
    from
        Games g1_0 
    left join
        Developers d1_0 
            on d1_0.id=g1_0.developerID 
    left join
        Genres g2_0 
            on g2_0.id=g1_0.genreID 
    left join
        Publishers p2_0 
            on p2_0.id=g1_0.publisherID 
    where
        g1_0.platformID=?
[Hibernate] 
    select
        g1_0.genreID,
        g1_0.id,
        g1_0.description,
        g1_0.developerID,
        d1_0.id,
        d1_0.developer,
        d1_0.email,
        g1_0.platformID,
        p1_0.id,
        p1_0.platform,
        g1_0.publisherID,
        p2_0.id,
        p2_0.email,
        p2_0.publisher,
        g1_0.release_date,
        g1_0.title 
    from
        Games g1_0 
    left join
        Developers d1_0 
            on d1_0.id=g1_0.developerID 
    left join
        Platforms p1_0 
            on p1_0.id=g1_0.platformID 
    left join
        Publishers p2_0 
            on p2_0.id=g1_0.publisherID 
    where
        g1_0.genreID=?
[Hibernate] 
    select
        g1_0.developerID,
        g1_0.id,
        g1_0.description,
        g1_0.genreID,
        g2_0.id,
        g2_0.genre,
        g1_0.platformID,
        p1_0.id,
        p1_0.platform,
        g1_0.publisherID,
        p2_0.id,
        p2_0.email,
        p2_0.publisher,
        g1_0.release_date,
        g1_0.title 
    from
        Games g1_0 
    left join
        Genres g2_0 
            on g2_0.id=g1_0.genreID 
    left join
        Platforms p1_0 
            on p1_0.id=g1_0.platformID 
    left join
        Publishers p2_0 
            on p2_0.id=g1_0.publisherID 
    where
        g1_0.developerID=?
@Entity(name = "Games")
public class GameEntity extends PanacheEntity {
    @Column(length = 100, nullable = false, unique = true)
    @NotBlank(message = "Title is required")
    private String title;

    @Column(length = 1000)
    private String description;

    @Column(name = "release_date")
    @Past(message = "Release date must be in the past or present")
    private LocalDate releaseDate;

    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "genreID", nullable = false)
    @NotNull(message = "Genre is required")
    private GenreEntity genre;

    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "publisherID", nullable = false)
    @NotNull(message = "Publisher is required")
    private PublisherEntity publisher;

    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "developerID", nullable = false)
    @NotNull(message = "Developer is required")
    private DeveloperEntity developer;

    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "platformID", nullable = false)
    @NotNull(message = "Platform is required")
    private PlatformEntity platform;

    @OneToMany(mappedBy = "game", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ReviewEntity> reviews;
    
    /// getters, setters, toString
}
@Entity(name = "Genres")
public class GenreEntity extends PanacheEntity {
    @Column(length = 50, nullable = false, unique = true)
    @NotBlank(message = "Genre name is required")
    private String genre;

    @OneToMany(mappedBy = "genre", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<GameEntity> games;

    /// getters, setters, toString
}
@ApplicationScoped
public class GameService {
    @Inject
    GameRepository repository;
    @Inject
    GenreRepository genreRepository;
    @Inject
    PublisherRepository publisherRepository;
    @Inject
    DeveloperRepository developerRepository;
    @Inject
    PlatformRepository platformRepository;


    public List<GameDTO> getAll() {
        return repository.listAll()  // Optional sorting
                .stream()
                .map(this::mapToDto)
                .toList();
    }

    @Transactional
    public void create(GameDTO dto) {
        GameEntity entity = mapToEntity(dto);
        repository.persist(entity);
    }

    @Transactional
    public void update(Long id, GameDTO dto) {
        GameEntity updatedEntity = mapToEntity(dto);
        GameEntity entity = repository.findById(id);
        if (entity == null)
            throw new NotFoundException("Game not found with id: " + id);

        entity.setTitle(updatedEntity.getTitle());
        entity.setDescription(updatedEntity.getDescription());
        entity.setReleaseDate(updatedEntity.getReleaseDate());
        entity.setGenre(updatedEntity.getGenre());
        entity.setPublisher(updatedEntity.getPublisher());
        entity.setDeveloper(updatedEntity.getDeveloper());
        entity.setPlatform(updatedEntity.getPlatform());

        repository.persist(entity);
    }

    @Transactional
    public void delete(Long id) {
        GameEntity entity = repository.findById(id);
        if (entity == null)
            throw new NotFoundException("Game not found with id: " + id);

        repository.delete(entity);
    }

    private GameEntity mapToEntity(GameDTO dto) {
        GenreEntity genre = genreRepository.findByGenre(dto.getGenre());
        if (genre == null)
            throw new NotFoundException("Genre not found.");
        PublisherEntity publisher = publisherRepository.findByPublisher(dto.getPublisher());
        if (publisher == null)
            throw new NotFoundException("Publisher not found.");
        DeveloperEntity developer = developerRepository.findByDeveloper(dto.getDeveloper());
        if (developer == null)
            throw new NotFoundException("Developer not found.");
        PlatformEntity platform = platformRepository.findByPlatform(dto.getPlatform());
        if (platform == null)
            throw new NotFoundException("Platform not found.");

        GameEntity entity = new GameEntity();
        entity.setTitle(dto.getTitle());
        entity.setDescription(dto.getDescription());
        entity.setReleaseDate(dto.getReleaseDate());
        entity.setGenre(genre);
        entity.setPublisher(publisher);
        entity.setDeveloper(developer);
        entity.setPlatform(platform);
        return entity;
    }

    private GameDTO mapToDto(GameEntity e) {
        return new GameDTO(
                e.getID(),
                e.getTitle(),
                e.getDescription(),
                e.getReleaseDate(),
                e.getGenre().getGenre(),
                e.getPublisher().getPublisher(),
                e.getDeveloper().getDeveloper(),
                e.getPlatform().getPlatform()
        );
    }
}
@ApplicationScoped
@Path("api/v1/games")
public class GameResource {

    @Inject
    GameService service;

    @GET
    public Response getAll() {
        List<GameDTO> list = service.getAll();
        return Response
                .ok(list)
                .build();
    }

    @POST
    public Response create(GameDTO dto) {
        service.create(dto);
        return Response
                .status(Response.Status.CREATED)
                .entity(dto)
                .build();
    }

    @PUT
    @Path("/{id}")
    public Response update(@PathParam("id") Long id, GameDTO dto) {
        service.update(id, dto);
        return Response
                .ok(dto)
                .build();
    }

    @DELETE
    @Path("/{id}")
    public Response delete(@PathParam("id") Long id) {
        service.delete(id);
        return Response
                .noContent()
                .build();
    }
}
java postgresql hibernate quarkus swagger-ui
1个回答
0
投票

解决方案是使用本机查询,它绕过 hibernate 所做的所有加载并直接执行删除命令:

@Transactional
    public void delete(Long id) {
        long deleted = repository.delete("id", id);
        if (deleted == 0) {
            throw new NotFoundException("Game not found with id: " + id);
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.