[英]Liberty JavaEE 8 catch ConstraintViolationException
Is there any way to catch org.hibernate.exception.ConstraintViolationException
in Liberty application server ?有什么方法可以在 Liberty 应用程序服务器中捕获
org.hibernate.exception.ConstraintViolationException
吗?
I have a this repository code :我有一个这个存储库代码:
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class MarketRepository {
@PersistenceContext
private EntityManager em;
@Resource
private UserTransaction tx;
public void insert(Market market) {
try {
tx.begin();
em.persist(market);
tx.commit();
} catch (Exception ignore) {
}
}
}
I always receive this exception :我总是收到这个例外:
[INFO] Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
[INFO] at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:109)
[INFO] at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
[INFO] at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
[INFO] at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
[INFO] at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)
[INFO] at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3238)
[INFO] at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3763)
[INFO] at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:107)
[INFO] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
[INFO] at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
[INFO] at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:723)
[INFO] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
[INFO] at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)
[INFO] at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
[INFO] at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
[INFO] at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1360)
[INFO] ... 20 more
[INFO] Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "ukmn9r4yewa9epwp1ekfsbm69gu"
[INFO] Detail: Key (exchange, symbol)=(COINEX, ZECUSDT) already exists.
[INFO] at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2533)
[INFO] at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2268)
[INFO] at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:313)
[INFO] at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:448)
[INFO] at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:369)
[INFO] at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:159)
[INFO] at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:125)
[INFO] at jdk.internal.reflect.GeneratedMethodAccessor1090.invoke(Unknown Source)
[INFO] at java.base/java.lang.reflect.Method.invoke(Method.java:567)
[INFO] at org.postgresql.ds.PGPooledConnection$StatementHandler.invoke(PGPooledConnection.java:428)
[INFO] at jdk.proxy11/jdk.proxy11.$Proxy136.executeUpdate(Unknown Source)
[INFO] at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.executeUpdate(WSJdbcPreparedStatement.java:520)
[INFO] at [internal classes]
[INFO] at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
[INFO] ... 31 more
this is my server.xml config :这是我的 server.xml 配置:
<dataSource jndiName="jdbc/jta-datasource" transactional="true">
<jdbcDriver id="database-driver" libraryRef="project-libs"/>
<properties databaseName="${database.name}" serverName="${database.hostname}" portNumber="${database.port}"
user="${database.username}" password="${database.password}"/>
</dataSource>
so, I want to ignore this exception, but still receive that !所以,我想忽略这个异常,但仍然收到!
How can fix this problem ?如何解决这个问题?
UPDATE:更新:
persistence.xml持久化文件
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="db-connection" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/jta-datasource</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL10Dialect"/>
</properties>
</persistence-unit>
</persistence>
MarketJob:市场工作:
import javax.ejb.*;
@Singleton
public class MarketJob {
@EJB
private MarketRepository repo;
@Lock(LockType.READ)
@Schedule(second = "59", minute = "59", hour = "*", persistent = false)
private void execute() {
List<Market> marketList = // read data from external api;
for (Market market : marketList) {
repo.insert(market);
}
}
}
If you use em.merge(market);
如果你使用
em.merge(market);
instead of em.persist(market);
而不是
em.persist(market);
JPA translates that to an insert-if-absent-else-update, which will avoid violating the constraint in your database that every (exchange, symbol) pairing be unique. JPA 将其转换为 insert-if-absent-else-update,这将避免违反数据库中每个(交换、符号)配对都是唯一的约束。
This may not work if the unique constraint isn't a primary key.如果唯一约束不是主键,这可能不起作用。 Or even if it is ... My experience is you just can't catch an exception that the persistence container is throwing.
或者即使是......我的经验是你无法捕捉到持久性容器抛出的异常。 One solution would be to make sure there isn't already a record with the same exchange and symbol:
一种解决方案是确保没有具有相同交换和符号的记录:
String jpql = "select count(*) from Market where m.exchange = ? and m.symbol = ?";
tx.begin();
int count = em.createQuery(jpql, Integer.class)
.setParameter(1, market.getExchange())
.setParameter(2, market.getSymbol()).getSingleResult();
if(count == 0){
em.persist(market);
tx.commit();
}
You just need to put arround the repo.insert(market)
a try/catch
block that catches SQLIntegrityConstraintViolationException
, and do whatever you want in the catch
block.您只需要在
repo.insert(market)
放置一个捕获SQLIntegrityConstraintViolationException
的try/catch
块,然后在catch
块中执行您想做的任何操作。
Off-topic recomendation for your code对您的代码的离题推荐
UserTransaction: At least in the example you are using you don't need that. UserTransaction:至少在您使用的示例中,您不需要它。 All Session Bean (aka EJB) (that is Stateless, Stateful and Singleton) provide transactionality by default.
默认情况下,所有会话 Bean(又名 EJB)(即无状态、有状态和单例)都提供事务性。 That means that before any business method a new transaction will automatically start, and will commit it at the end of the method.
这意味着在任何业务方法之前,一个新事务将自动启动,并在方法结束时提交。 If the method throws an Exception the transaction will automatically Rollback.
如果该方法抛出异常,事务将自动回滚。
If the business method is called from another EJB it will reuse the same transaction.如果从另一个 EJB 调用业务方法,它将重用相同的事务。
That is the default behaviour, and is really really powerful, allowing to manage most of the business cases without manually managing transactions.这是默认行为,非常强大,允许管理大多数业务案例而无需手动管理事务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.