在Quarkus中捕获Hibernate异常

iaqfqrcu  于 2023-10-23  发布在  其他
关注(0)|答案(4)|浏览(120)

我正在尝试使用Quarkus构建一个小型REST服务。我使用Hibernate和PostgreSQL数据库。它在所有好的情况下都很好用。但是当有像ConstraintViolationException这样的Hibernate异常时,我无法以正常的方式捕获它们。这些异常被 Package 到其他异常ArcUndeclaredThrowableExceptionRollbackException中。所以异常可以通过使用

catch (ArcUndeclaredThrowableException e) {
...
}

仓库

@Dependent
public class UserRepository {

    @Transactional
    public void createUser(User user) {
        getEntityManager().persist(user); //<- the constraint violation happens at commit, so when transaction will be closed
    }
}

资源

@Override
    public Response createUser(@Valid CreateUserDTO createUserDTO, UriInfo uriInfo) {
        ...
        try {
            userRepository.createUser(user);
        } catch (ArcUndeclaredThrowableException e) { //<- here the hibernate exception should be catchable
            log.error(e.getMessage());
            throw e;
        }
        return Response.ok().build();
    }

由于这个问题,也无法为Hibernate添加ExceptionMapper。有没有人遇到过类似的问题,或者我的代码有普遍的问题?我用的是Java11。

3df52oht

3df52oht1#

我会这样做:

try {
        getEntityManager().persist(user);
        getEntityManager().flush();
} catch(ConstraintViolationException e) {
    throw new MyCustomException(e);
}

并为MyCustomException创建异常Map器。

xfb7svmp

xfb7svmp2#

您可以刷新Hibernate会话,这应该会触发像ConstraintViolationException这样的异常,而无需提交事务。
在你的情况下,这应该是这样的

@Dependent
public class UserRepository {

    @Transactional
    public void createUser(User user) {
        getEntityManager().persist(user);
        getEntityManager().flush();// should triger ConstraintViolationException
    }
}
yyyllmsg

yyyllmsg3#

我今天遇到了同样的问题,找到了一个解决办法。问题是,据我所知,Arc(quarkus的cdi实现)有时需要生成类。
异常(如javax.transaction.RollbackExcpetion)需要以某种方式传播给用户。因此,选中的Exception被 Package 在ArcUncertaintedThrowableException中。但是,只有当您不显式处理异常时才需要这样做。
例如,你可以只声明一个异常:

@Dependent
public class UserRepository {

    @Transactional
    public void createUser(User user) throws RollbackException{
        getEntityManager().persist(user);
    }
}

在资源中,您可以捕获RollbackException

@Override
public Response createUser(@Valid CreateUserDTO createUserDTO, UriInfo uriInfo) {
    ...
    try {
        userRepository.createUser(user);
    } catch (RollbackException e) {
        log.error(e.getMessage());
        throw e;
    }
    return Response.ok().build();
}
pftdvrlh

pftdvrlh4#

import jakarta.transaction.RollbackException
import jakarta.ws.rs.core.Response
import jakarta.ws.rs.ext.ExceptionMapper
import jakarta.ws.rs.ext.Provider

@Provider
@Singleton
open class RollbackExceptionMapper : ExceptionMapper<RollbackException> {
    
    override fun toResponse(exception: RollbackException): Response {
        if (exception.cause is TheHibernateExceptionWhatYouNeedToHandleWithException) {
            // TODO handle what you need
            return
        }

        // Other If condition you want

        throw exception
    }
}

我在后端使用Kotlin,但你也可以使用Java。

相关问题