Nie ma potrzeby pisania niestandardowego kodu, aby to osiągnąć - Hibernacja domyślnie rejestruje przyczynę wyjątku. Jeśli tego nie widzisz, rejestrowanie w trybie hibernacji nie może być poprawnie skonfigurowane. Oto przykład z slf4j + log4j i używanie Maven do zarządzania zależnościami.
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>
Wykonywanie główną metodę następnie zalogować się, co następuje:
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"
To chyba warto wspomnieć, że można wyłączyć dozowanie JDBC, która otacza oryginalnego wyjątku przez ustawienie Właściwość hibernate.jdbc.batch_size
do 0
(nie trzeba dodawać, że prawdopodobnie nie chcesz tego robić w produkcji.)
W jaki sposób wypisujesz wyjątek? Moje doświadczenie z log4j i slf4j, dostaję spowodowane przez linie za darmo ... – mjwenk
Biblioteki rejestrowania wydrukują przyczynę, ale robią tak, jeśli excption następuje zgodnie z konwencją łańcuchów wyjątków. tj. każdy wyjątek powinien zwracać swoją bezpośrednią przyczynę źródłową za pomocą metody getCause(). Wygląda na to, że wyjątek SQLException nie jest zgodny z tą konwencją. Łączony artykuł wyjaśnia to samo. Autor napisał zatem aspekt, który pobiera obiekt zwracany przez getNextException() i ustawia go jako przyczynę w wyjątku nadrzędnym. – Dojo
@Priyank 'SQLException' używa łańcucha wyjątków (który można iterować za pomocą iteratora lub używając' getNextException() '), gdy wystąpi wiele wyjątków (niepowiązanych?). Ta koncepcja jest prostopadła do łańcucha przyczyn. W tym konkretnym przypadku uważam, że powinna być ustalona jako przyczyna. –