2017-11-08 4 views
0

Ich habe stackoverflow gesucht und versucht, verschiedene Ausnahmen wie in den vorherigen Antworten zu fangen, aber nichts hat funktioniert.Umgang mit JPA's @Column (unique = true) Ausnahme

My Model-Klasse ist:

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.Table; 

@Entity 
@Table 
public class User { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int id; 

    @Column(nullable = false) 
    private String name; 

    @Column(nullable = false, unique = true) 
    private String username; 

    @Column(nullable = false) 
    private String password; 
    ... 
    ... 
} 

-Code funktioniert, wenn Benutzername noch nicht vorhanden ist. Wenn der Benutzer jedoch versucht, einen Benutzer mit einem Benutzernamen hinzuzufügen, der bereits in db vorhanden ist, löst er die Ausnahme @Column(nullable = false) aus. Mein Ziel ist es, diesen Fehler zu finden und den Dialog "Duplicate Benutzername" anzuzeigen. Aber ich bin nicht in der Lage, es zu fangen. Dies ist meine Methode Benutzer zu db hinzuzufügen:

@Override 
public void addUser(User user) { 
    SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); 
    Session session = sessionFactory.openSession(); 
    try { 

     session.beginTransaction(); 
     session.save(user); 
    } catch (PersistenceException e) { 
     System.out.println("username already exist"); 
    } 

    session.getTransaction().commit(); 
    session.close(); 
    sessionFactory.close(); 

} 

Wie bereits erwähnt, ich habe „Hit and trial“ -ed viele Ausnahmen Klassen, aber nichts scheint zu funktionieren. Es zeigt folgenden Fehler an:

Hibernate: select next_val as id_val from hibernate_sequence for update 
Hibernate: update hibernate_sequence set next_val= ? where next_val=? 
Hibernate: insert into User (id, password, username) values (?, ?, ?) 
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149) 
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157) 
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164) 
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1443) 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:493) 
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3207) 
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2413) 
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467) 
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:156) 
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) 
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231) 
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68) 
    at com.ultranet.servicesImpl.UserServiceImpl.addUser(UserServiceImpl.java:57) 
    at com.ultranet.main.DriverClass.main(DriverClass.java:20) 
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:178) 
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45) 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3013) 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3513) 
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:589) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) 
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1437) 
    ... 10 more 
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'admint' for key 'UK_jreodf78a7pl5qidfh43axdfb' 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) 
    at java.lang.reflect.Constructor.newInstance(Unknown Source) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406) 
    at com.mysql.jdbc.Util.getInstance(Util.java:381) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542) 
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2019) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1937) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1922) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175) 
    ... 19 more 

Also, wie bekomme ich diese Ausnahme, so dass ich benutzerfreundliche Nachricht anzeigen kann? P. S: Einige der Ausnahmen habe ich versucht zu kontrollieren sind:

java.sql.SQLException; 
java.sql.SQLIntegrityConstraintViolationException; 
javax.persistence.EntityExistsException; 
javax.persistence.PersistenceException; 
javax.transaction.RollbackException; 
org.hibernate.HibernateException; 
org.hibernate.exception.ConstraintViolationException; 
org.springframework.dao.DataIntegrityViolationException; 
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException; 
+0

Haben Sie versucht, org.hibernate.exception.ConstraintViolationException und com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException zu erfassen? Ich denkehibernate wirft org.hibernate.exception.ConstraintViolationException auf addUser-Funktion, sobald die sql-Ausnahme auftritt – manoj

+0

ist der Wert "admint" In Feld Benutzername möglicherweise bereits vorhanden ist? –

Antwort

1

DB Ausnahmen immer tödlich sein sollte, das ist, warum sie Laufzeit sind. Aus meiner Sicht sollten Sie sich verifizieren, ob ein Benutzer mit diesem Benutzernamen bereits existiert, bevor Sie versuchen, ihn zu erstellen. Sie können dann eine benutzerdefinierte Ausnahme generieren, die von einem höheren Code erfasst wird, der dem Endbenutzer angezeigt wird.

+0

Großartig! Danke, Alter. Ich habe diesen Schritt schon einmal ausprobiert, aber ich weiß, warum mein Verstand diesmal rutschte. Kann ich diesen Schritt trotzdem über Ausnahmen umsetzen? ich meine, indem ich die verletzte Beschränkung "fange"? – realpac

+0

Wie Sie selbst sehen, ist es ziemlich empfindlich. Sie sollten wirklich Existenz mit einem ausgewählten Benutzer u von Benutzer prüfen, who u.username = ..... und wenn das Ergebnis Elemente hat, wirf deine Ausnahme. Wenn Sie versuchen, Ausnahmen zu fangen, sind Sie abhängig von Frühling oder Winterschlaf ... was nicht gut ist – ThePoltergeist

1

Zunächst wird Ihnen die Annotation "unique = true" zur Laufzeit nicht helfen. Es beschreibt, wie das Datenbankschema aussehen soll. Schema-Mapper lesen diese Annotation und stellen sicher, dass die Spalte eindeutig ist.

In Ihrem Fall haben Sie versucht, ungültige Daten einzufügen, und Sie haben eine "MySQLIntegrityConstraintViolationException" erhalten. Es ist nicht einfach, weitere Details zu dem Problem zu finden. Wie auch immer, die Persistenz ist fehlgeschlagen und setzt Ihren aktuellen Persistenzkontext in einen Fehler/Rollback-Zustand. Normalerweise willst du nicht hier enden.

Es empfiehlt sich, einen Validierungsschritt hinzuzufügen, um dies vollständig zu vermeiden. Fragen Sie die Datenbank nach diesem Benutzernamen ab - und wenn es bereits existiert, zeigen Sie das Validierungsproblem an. Wenn es zwei Prozesse gäbe, die versuchen, denselben Benutzernamen zur gleichen Zeit einzufügen, würden Sie immer noch auf das anfängliche Problem stoßen, aber die Chancen sind sehr gering, wenn Sie die Validierung NUR vor dem Fortsetzen durchführen.

0

Ich denke, Ihre Funktion Arbeit gut zu kontrollieren, aber das Problem ist commit danach:
session.getTransaction().commit(); Sie diese Transaktion in Ihrem Catch-Block Rollback sollte, aber nicht aus, dass zu begehen.

Sie können überprüfen, welche Zeile Ihres Codes diese Ausnahme auslöst. In dir irr log, es heißt es ist UserServiceImpl.addUser(UserServiceImpl.java:57).

Verwandte Themen