Hibernate 不允许我处理错误凭据的异常
Hibernate do not let me handle exception on wrong credentials
首先我要说的是,我尝试了很多关于这个主题的资料,但找不到任何对此事有帮助的文件。如果我遗漏了什么,我提前道歉。
我使用带 Hibernate 5.4 和 JavaFX 的 Eclipse 来管理桌面应用程序,该应用程序将要求用户以交互方式提供数据库凭据,并使用该信息覆盖休眠上的 属性-cfg.xml 文件。这部分正在全面运作。
当我想处理用户提供错误凭据的极有可能情况时,我的问题就来了。看起来休眠不允许我处理我在代码中使用的任何异常。
有人可以看看并建议我应该改进哪些地方以便能够处理这些问题吗?
这是我的代码,我将在其中尝试使用用户提供的信息构建 sectionFactory。我希望在 task.setOnFailed 上处理错误凭据的事件,但从未调用过,无论发生什么 task.setOnSucceeded 总是被调用。
//Task to connect to DB
private void taskDBConnection() {
// Create a background Task
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
actionTarget.setText("Attempt to login to database");
HibernateUtil.getSessionFactory();
return null;
}
};
// This method allows us to handle any Exceptions thrown by the task
task.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent arg0) {
System.out.println("Failed LoginView.java setOnFailed");
task.getException().printStackTrace();
}
});
// If the task completed successfully, perform other updates here
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent arg0) {
System.out.println("Done LoginView.java setOnSucceeded");
loginStage.close();
}
});
// Now, start the task on a background thread
new Thread(task).start();
}
这是我的 sessionFactory 构建器 class,同样,那里的 catch 异常从未被调用。
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
//Create the config file / legacy but still works
Configuration hibernateConfig = new Configuration().configure(new File(Paths.get("").toAbsolutePath().toString() + "\Config\hibernate.cfg.xml"));
hibernateConfig.setProperty("hibernate.connection.username", getUsername());
hibernateConfig.setProperty("hibernate.connection.password", getPassword());
// Creating a registry
//registry = new StandardServiceRegistryBuilder().configure(new File(Paths.get("").toAbsolutePath().toString() + "\Config\hibernate.cfg.xml")).build();
registry = new StandardServiceRegistryBuilder().applySettings(hibernateConfig.getProperties()).build();
// Create the MetadataSources
MetadataSources sources = new MetadataSources(registry);
sources.addAnnotatedClass(Class1.class);
sources.addAnnotatedClass(Class2.class);
// Create the Metadata
Metadata metadata = sources.getMetadataBuilder().build();
// Create SessionFactory
sessionFactory = metadata.getSessionFactoryBuilder().build();
} catch (Exception e) {
e.printStackTrace();
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
}
return sessionFactory;
}
以下是我在 Eclipse 上遇到的错误。它很长,所以我只 post 第一部分。我当然知道异常是什么(我强迫它发生),但我想以一种方式处理它,通知用户他们不正确并允许他们重试。
WARNING: com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@87315ad -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (1). Last acquisition attempt exception:
java.sql.SQLException: ORA-01017: invalid username/password; logon denied
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:392)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:385)
at oracle.jdbc.driver.T4CTTIfun.processError(T4CTTIfun.java:1018)
at oracle.jdbc.driver.T4CTTIoauthenticate.processError(T4CTTIoauthenticate.java:501)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:437)
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:954)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:639)
at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:666)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:566)
at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:175)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:220)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:206)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolPooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:203)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1138)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1125)
at com.mchange.v2.resourcepool.BasicResourcePool.access0(BasicResourcePool.java:44)
at com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1870)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)
然后休眠。cfg.xml
<session-factory>
<property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@database:1521:schema</property>
<property name="dialect">org.hibernate.dialect.Oracle8iDialect</property>
<property name="show_sql">true</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.acquireRetryAttempts">1</property>
<property name="hibernate.c3p0.acquireRetryDelay">2500</property>
</session-factory>
万一有人好奇,我通过处理任何抛出的异常并在我的应用程序的标签中打印此消息,设法使它或多或少地按我想要的方式工作。
我将始终通过使用 Optional 对其进行迭代来获得根异常,因此当它是错误的凭据时,JDBC 会将其作为结果。
catch (Exception e) {
Optional<Throwable> rootCause = Stream.iterate(e, Throwable::getCause)
.filter(element -> element.getCause() == null)
.findFirst();
System.out.println(rootCause.get().getClass().getSimpleName() + " - " + rootCause.get().getMessage());}
首先我要说的是,我尝试了很多关于这个主题的资料,但找不到任何对此事有帮助的文件。如果我遗漏了什么,我提前道歉。
我使用带 Hibernate 5.4 和 JavaFX 的 Eclipse 来管理桌面应用程序,该应用程序将要求用户以交互方式提供数据库凭据,并使用该信息覆盖休眠上的 属性-cfg.xml 文件。这部分正在全面运作。 当我想处理用户提供错误凭据的极有可能情况时,我的问题就来了。看起来休眠不允许我处理我在代码中使用的任何异常。
有人可以看看并建议我应该改进哪些地方以便能够处理这些问题吗?
这是我的代码,我将在其中尝试使用用户提供的信息构建 sectionFactory。我希望在 task.setOnFailed 上处理错误凭据的事件,但从未调用过,无论发生什么 task.setOnSucceeded 总是被调用。
//Task to connect to DB
private void taskDBConnection() {
// Create a background Task
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
actionTarget.setText("Attempt to login to database");
HibernateUtil.getSessionFactory();
return null;
}
};
// This method allows us to handle any Exceptions thrown by the task
task.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent arg0) {
System.out.println("Failed LoginView.java setOnFailed");
task.getException().printStackTrace();
}
});
// If the task completed successfully, perform other updates here
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent arg0) {
System.out.println("Done LoginView.java setOnSucceeded");
loginStage.close();
}
});
// Now, start the task on a background thread
new Thread(task).start();
}
这是我的 sessionFactory 构建器 class,同样,那里的 catch 异常从未被调用。
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
//Create the config file / legacy but still works
Configuration hibernateConfig = new Configuration().configure(new File(Paths.get("").toAbsolutePath().toString() + "\Config\hibernate.cfg.xml"));
hibernateConfig.setProperty("hibernate.connection.username", getUsername());
hibernateConfig.setProperty("hibernate.connection.password", getPassword());
// Creating a registry
//registry = new StandardServiceRegistryBuilder().configure(new File(Paths.get("").toAbsolutePath().toString() + "\Config\hibernate.cfg.xml")).build();
registry = new StandardServiceRegistryBuilder().applySettings(hibernateConfig.getProperties()).build();
// Create the MetadataSources
MetadataSources sources = new MetadataSources(registry);
sources.addAnnotatedClass(Class1.class);
sources.addAnnotatedClass(Class2.class);
// Create the Metadata
Metadata metadata = sources.getMetadataBuilder().build();
// Create SessionFactory
sessionFactory = metadata.getSessionFactoryBuilder().build();
} catch (Exception e) {
e.printStackTrace();
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
}
return sessionFactory;
}
以下是我在 Eclipse 上遇到的错误。它很长,所以我只 post 第一部分。我当然知道异常是什么(我强迫它发生),但我想以一种方式处理它,通知用户他们不正确并允许他们重试。
WARNING: com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@87315ad -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (1). Last acquisition attempt exception:
java.sql.SQLException: ORA-01017: invalid username/password; logon denied
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:392)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:385)
at oracle.jdbc.driver.T4CTTIfun.processError(T4CTTIfun.java:1018)
at oracle.jdbc.driver.T4CTTIoauthenticate.processError(T4CTTIoauthenticate.java:501)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:437)
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:954)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:639)
at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:666)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:566)
at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:175)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:220)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:206)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolPooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:203)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1138)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1125)
at com.mchange.v2.resourcepool.BasicResourcePool.access0(BasicResourcePool.java:44)
at com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1870)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)
然后休眠。cfg.xml
<session-factory>
<property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@database:1521:schema</property>
<property name="dialect">org.hibernate.dialect.Oracle8iDialect</property>
<property name="show_sql">true</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.acquireRetryAttempts">1</property>
<property name="hibernate.c3p0.acquireRetryDelay">2500</property>
</session-factory>
万一有人好奇,我通过处理任何抛出的异常并在我的应用程序的标签中打印此消息,设法使它或多或少地按我想要的方式工作。 我将始终通过使用 Optional 对其进行迭代来获得根异常,因此当它是错误的凭据时,JDBC 会将其作为结果。
catch (Exception e) {
Optional<Throwable> rootCause = Stream.iterate(e, Throwable::getCause)
.filter(element -> element.getCause() == null)
.findFirst();
System.out.println(rootCause.get().getClass().getSimpleName() + " - " + rootCause.get().getMessage());}