不需要编写任何自定义代码来实现这一点 - Hibernate 默认会记录异常原因。如果您看不到这一点,则一定是没有正确设置 Hibernate 日志记录。这是一个使用 slf4j+log4j 的示例,并使用 Maven 进行依赖管理。
src/main/java/pgextest/PGExceptionTest.java
public class PGExceptionTest {
public static void main(String[] args) throws Exception {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(
"pgextest");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
// here I attempt to persist an object with an ID that is already in use
entityManager.persist(new PGExceptionTestBean(1));
entityManager.getTransaction().commit();
entityManager.close();
}
}
src/main/resources/log4j.properties
log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
src/main/resources/META-INF/persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="pgextest">
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/pgextest"/>
<property name="javax.persistence.jdbc.user" value="postgres"/>
<property name="javax.persistence.jdbc.password" value="postgres"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.jdbc.batch_size" value="5"/>
</properties>
</persistence-unit>
</persistence>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pgextest</groupId>
<artifactId>pgextest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.6.9.Final</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901.jdbc4</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
然后执行 main 方法将记录以下内容:
ERROR [main] - Batch entry 0 insert into PGExceptionTestBean (label, id) values (NULL, '1') was aborted. Call getNextException to see the cause.
ERROR [main] - ERROR: duplicate key value violates unique constraint "pgexceptiontestbean_pkey"
可能值得一提的是,您可以通过将属性设置为来禁用包装原始异常的 JDBC 批处理hibernate.jdbc.batch_size
(0
不用说您可能不想在生产中这样做。)