- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将旧版 Web 应用程序从 JBoss 4.2.3GA 迁移到 Wildfly 9。
此迁移的一部分需要从 Hibernate 3.2 升级到 Hibernate 4.3.10
我对 Hibernate 的了解很少,所以如果我遗漏了一些明显的东西,请原谅我,但是我在网上找不到任何东西来解释我遇到的问题。
Web 应用程序本身具有 ConnectionProvider 接口(interface)的自定义实现。
重构前的MyConnectionProvider
package com.my_package.data;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import java.util.logging.Logger;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.connection.ConnectionProviderFactory;
import org.hibernate.util.NamingHelper;
/**
* An implementation of the {@link ConnectionProvider} interface. This class
* requires the <code>hibernate.connection.datasource</code> property to be
* set to the JNDI name of the DataSource to provide connections from, or a
* DataSource to be injected before the {@link #configure(Properties)} method
* is called. This supports use by the {@link Database} class and the Hibernate
* implementation of the {@link javax.persistence.EntityManager}.
*
*/
public class MyConnectionProvider implements ConnectionProvider
{
private static final Logger LOGGER = Logger.getLogger(MyConnectionProvider.class.getName());
private static final String JNDI_NAME_KEY = "hibernate.connection.datasource";
private static final String JNDI_NAME_KEY_STANDBY = "StandbyDatasource";
private static final ThreadLocal<String> USER_NAME = new ThreadLocal<String>();
private static final ThreadLocal<String> PASSWORD = new ThreadLocal<String>();
private DataSource dataSource;
private DataSource[] dataSources;
private DataSource lastMaster;
private DataSource standby;
/**
* Instantiate an instance of this class. This is called by the {@link
* ConnectionProviderFactory} class so must be public.
*/
public MyConnectionProvider()
{
super();
}
/**
* Configure the connection provider. If a DataSource has not been
* explicitly injected by {@link #setDataSource(DataSource)} then the JNDI
* name for the DataSource must be provided.
*
* @param props The configuration properties. The property
* <code>hibernate.connection.datasource</code> should be set
* and point to the JNDI name of the DataSource.
*
* @see org.hibernate.connection.ConnectionProvider#configure(java.util.Properties)
*/
public void configure(Properties props) throws HibernateException
{
String jndiName = props.getProperty(JNDI_NAME_KEY);
String jndiStandbyName = props.getProperty(JNDI_NAME_KEY_STANDBY);
/*
* either a JNDI name should be present or a DataSource should have been
* injected
*/
if (jndiName == null && this.dataSource == null)
{
throw new HibernateException("Datasource not set explicitly and JNDI name not specified");
}
/* if no DataSource was injected then use JNDI to look one up */
if (this.dataSource == null)
{
try
{
// Assume the first database is master - at least one needs to be configured
this.dataSource = (DataSource) NamingHelper.getInitialContext(props).lookup(
props.getProperty(JNDI_NAME_KEY));
// Copy the datasource to another to keep the references throughout the
// code the same if only using a single datasource or floating IP.
this.lastMaster = this.dataSource;
}
catch (NamingException e)
{
throw new HibernateException("There was a problem retrieving the primary data source", e);
}
try
{
// Is there a standby datasource configured
if (jndiStandbyName != null)
{
// Set up the standby data source
this.standby = null;
// Read the standby datasource which has been added to props.
this.standby = (DataSource) NamingHelper.getInitialContext(props).lookup(
props.getProperty(JNDI_NAME_KEY_STANDBY));
// Add both data sources
dataSources = new DataSource[]{lastMaster,standby};
}
}
catch (NamingException e)
{
// The standby datasource was not found - log out.
System.err.println("Standby data source not configured");
}
if (this.dataSource == null)
{
throw new HibernateException("The primary data source wasn't found");
}
}
}
/**
* Utility method used to determine if an SQL exception is caused by invalid user
* credentials being provided by the client.
*
* @param e The SQLException raised when attempting to open a connection.
* @return boolean flag, true if the exception is related to invalid login, or
* false if the exception is raised for some other reason.
*/
public static boolean isLoginException(SQLException e)
{
/* Switch on the error code */
switch(e.getErrorCode())
{
case 1004 : /* FALLTHROUGH: ORA-01004 null password given; logon denied */
case 1017 : /* FALLTHROUGH: ORA-01017 invalid username/password; logon denied */
case 1040 : /* FALLTHROUGH: ORA-01040 invalid character in password; logon denied (multibyte character issue) */
case 17443 : /* ORA-17443 null username or password not supported by thin driver */
break;
default :
break;
}
return false;
}
/**
* Get a configured connection.
*
* @return the connection to the database.
* @throws SQLException if there was a problem retrieving the connection.
*
* @see org.hibernate.connection.ConnectionProvider#getConnection()
*/
public Connection getConnection() throws SQLException
{
Connection conn;
CallableStatement stmt = null;
ResultSet rs = null;
String userName = USER_NAME.get();
String password = PASSWORD.get();
try
{
/* if a user name or password are specified then retrieve a connection using these criteria */
if (userName != null || password != null)
{
// Set the connection. Don't return it yet as it may be a standby
conn = lastMaster.getConnection(userName, password);
}
else /* use the data source parameters to retrieve the connection */
{
// Set the connection. Don't return it yet as it may be a standby
conn = lastMaster.getConnection();
}
// See if the connection is to the master and is ok
// This will throw a SQL exception if the application is not running or the
// connection is being made to the standby
stmt = conn.prepareCall("{call oracle_package.stored_procedure_check_sys_state}");
stmt.executeUpdate();
// If we get here then no exceptions have been thrown so its ok return connection
return conn;
}
catch(SQLException e)
{
/*
* Determine that the exception isn't simply a user credentials issue, if it
* is then we rethrow the exception, otherwise we see if there is an alternate
* connection to try.
*/
if (!isLoginException(e) && dataSources != null && dataSources.length > 1)
{
/* Determine the alternate data source */
DataSource alternate = dataSources[0] == lastMaster ? dataSources[1] : dataSources[0];
/* Attempt to open a conenction to the alternate datasource */
conn = (Connection)alternate.getConnection(userName, password);
/*
* If we opened a connection then update the lastMaster instance variable,
* If we didn't then an SQLException will have been thrown and we won't have
* reached this next instruction.
*/
lastMaster = alternate;
System.err.println("Problem with datasource - switching to next datasource");
return conn;
}
else
{
/* The caught exception cannot be handled here so propogate it. */
throw e;
}
}
}
/**
* Close a connection.
*
* @param conn the connection to close.
*
* @see org.hibernate.connection.ConnectionProvider#closeConnection(java.sql.Connection)
*/
public void closeConnection(Connection conn) throws SQLException
{
conn.close();
}
/**
* Close the connection provider.
*
* @see org.hibernate.connection.ConnectionProvider#close()
*/
public void close()
{
this.dataSource = null;
this.lastMaster = null;
this.standby = null;
}
/**
* Query whether this instance supports aggressive release of database
* connections.
*
* @return true as this implementation does support aggressive release of
* connections.
*
* @see ConnectionProvider#supportsAggressiveRelease()
*/
public boolean supportsAggressiveRelease()
{
return true;
}
/**
* Inject a DataSource into this connection provider. Must be provided
* before {@link MyConnectionProvider#configure(Properties)} is invoked
* if the DataSource is not being provided via JNDI.
*
* @param dataSource The dataSource to inject.
*/
public void setDataSource(DataSource dataSource)
{
if (dataSource != null)
{
LOGGER.info("Using injected DataSource");
}
this.dataSource = dataSource;
}
/**
* Set the user name to be used for connections retrieved by the current
* thread, when {@link #getConnection()} is called.
*
* @param userName the user name to use.
*/
public static final void setUserName(String userName)
{
MyConnectionProvider.USER_NAME.set(userName);
}
/**
* Set the password to be used for connections retrieved by the current
* thread, when {@link #getConnection()} is called.
*
* @param password the password to use.
*/
public static final void setPassword(String password)
{
MyConnectionProvider.PASSWORD.set(password);
}
}
我已将 jar 更新到 Hibernate 4.3.10 并重构代码以使用新的 ConnectionProvider 路径并停止使用不再存在的 NamingHelper Hibernate util 类(我不确定此重构是否正确/有效 - 任何)指针将不胜感激)。
重构后的MyConnectionProvider
package com.my_package.data;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.hibernate.HibernateException;
/*Refactored*/ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
/**
* An implementation of the {@link ConnectionProvider} interface. This class
* requires the <code>hibernate.connection.datasource</code> property to be
* set to the JNDI name of the DataSource to provide connections from, or a
* DataSource to be injected before the {@link #configure(Properties)} method
* is called. This supports use by the {@link Database} class and the Hibernate
* implementation of the {@link javax.persistence.EntityManager}.
*
*/
public class MyConnectionProvider implements ConnectionProvider
{
/*Refactored*/ private static final long serialVersionUID = -7542368426769408563L;
private static final Logger LOGGER = Logger.getLogger(MyConnectionProvider.class.getName());
private static final String JNDI_NAME_KEY = "hibernate.connection.datasource";
private static final String JNDI_NAME_KEY_STANDBY = "StandbyDatasource";
private static final ThreadLocal<String> USER_NAME = new ThreadLocal<String>();
private static final ThreadLocal<String> PASSWORD = new ThreadLocal<String>();
private DataSource dataSource;
private DataSource[] dataSources;
private DataSource lastMaster;
private DataSource standby;
/**
* Instantiate an instance of this class. This is called by the {@link
* ConnectionProviderFactory} class so must be public.
*/
public MyConnectionProvider()
{
super();
}
/**
* Configure the connection provider. If a DataSource has not been
* explicitly injected by {@link #setDataSource(DataSource)} then the JNDI
* name for the DataSource must be provided.
*
* @param props The configuration properties. The property
* <code>hibernate.connection.datasource</code> should be set
* and point to the JNDI name of the DataSource.
*
* @see org.hibernate.connection.ConnectionProvider#configure(java.util.Properties)
*/
public void configure(Properties props) throws HibernateException
{
String jndiName = props.getProperty(JNDI_NAME_KEY);
String jndiStandbyName = props.getProperty(JNDI_NAME_KEY_STANDBY);
/*
* either a JNDI name should be present or a DataSource should have been
* injected
*/
if (jndiName == null && this.dataSource == null)
{
throw new HibernateException("Datasource not set explicitly and JNDI name not specified");
}
/* if no DataSource was injected then use JNDI to look one up */
if (this.dataSource == null)
{
try
{
// Assume the first database is master - at least one needs to be configured
/*Refactored*/ Context initialContext = new InitialContext(props);
/*Refactored*/ this.dataSource = (DataSource) initialContext.lookup(props.getProperty(JNDI_NAME_KEY));
// Copy the datasource to another to keep the references throughout the
// code the same if only using a single datasource or floating IP.
this.lastMaster = this.dataSource;
}
catch (NamingException e)
{
throw new HibernateException("There was a problem retrieving the primary data source", e);
}
try
{
// Is there a standby datasource configured
if (jndiStandbyName != null)
{
// Set up the standby data source
this.standby = null;
// Read the standby datasource which has been added to props.
/*Refactored*/ Context initialContext = new InitialContext(props);
/*Refactored*/ this.standby = (DataSource) initialContext.lookup(props.getProperty(JNDI_NAME_KEY_STANDBY));
// Add both data sources
dataSources = new DataSource[]{lastMaster,standby};
}
}
catch (NamingException e)
{
// The standby datasource was not found - log out.
System.err.println("Standby data source not configured");
}
if (this.dataSource == null)
{
throw new HibernateException("The primary data source wasn't found");
}
}
}
/**
* Utility method used to determine if an SQL exception is caused by invalid user
* credentials being provided by the client.
*
* @param e The SQLException raised when attempting to open a connection.
* @return boolean flag, true if the exception is related to invalid login, or
* false if the exception is raised for some other reason.
*/
public static boolean isLoginException(SQLException e)
{
/* Switch on the error code */
switch(e.getErrorCode())
{
case 1004 : /* FALLTHROUGH: ORA-01004 null password given; logon denied */
case 1017 : /* FALLTHROUGH: ORA-01017 invalid username/password; logon denied */
case 1040 : /* FALLTHROUGH: ORA-01040 invalid character in password; logon denied (multibyte character issue) */
case 17443 : /* ORA-17443 null username or password not supported by thin driver */
break;
default :
break;
}
return false;
}
/**
* Get a configured connection.
*
* @return the connection to the database.
* @throws SQLException if there was a problem retrieving the connection.
*
* @see org.hibernate.connection.ConnectionProvider#getConnection()
*/
public Connection getConnection() throws SQLException
{
Connection conn;
CallableStatement stmt = null;
ResultSet rs = null;
String userName = USER_NAME.get();
String password = PASSWORD.get();
try
{
/* if a user name or password are specified then retrieve a connection using these criteria */
if (userName != null || password != null)
{
// Set the connection. Don't return it yet as it may be a standby
conn = lastMaster.getConnection(userName, password);
}
else /* use the data source parameters to retrieve the connection */
{
// Set the connection. Don't return it yet as it may be a standby
conn = lastMaster.getConnection();
}
// See if the connection is to the master and is ok
// This will throw a SQL exception if the application is not running or the
// connection is being made to the standby
stmt = conn.prepareCall("{call oracle_package.stored_procedure_check_sys_state}");
stmt.executeUpdate();
// If we get here then no exceptions have been thrown so its ok return connection
return conn;
}
catch(SQLException e)
{
/*
* Determine that the exception isn't simply a user credentials issue, if it
* is then we rethrow the exception, otherwise we see if there is an alternate
* connection to try.
*/
if (!isLoginException(e) && dataSources != null && dataSources.length > 1)
{
/* Determine the alternate data source */
DataSource alternate = dataSources[0] == lastMaster ? dataSources[1] : dataSources[0];
/* Attempt to open a conenction to the alternate datasource */
conn = (Connection)alternate.getConnection(userName, password);
/*
* If we opened a connection then update the lastMaster instance variable,
* If we didn't then an SQLException will have been thrown and we won't have
* reached this next instruction.
*/
lastMaster = alternate;
System.err.println("Problem with datasource - switching to next datasource");
return conn;
}
else
{
/* The caught exception cannot be handled here so propogate it. */
throw e;
}
}
}
/**
* Close a connection.
*
* @param conn the connection to close.
*
* @see org.hibernate.connection.ConnectionProvider#closeConnection(java.sql.Connection)
*/
public void closeConnection(Connection conn) throws SQLException
{
conn.close();
}
/**
* Close the connection provider.
*
* @see org.hibernate.connection.ConnectionProvider#close()
*/
public void close()
{
this.dataSource = null;
this.lastMaster = null;
this.standby = null;
}
/**
* Query whether this instance supports aggressive release of database
* connections.
*
* @return true as this implementation does support aggressive release of
* connections.
*
* @see ConnectionProvider#supportsAggressiveRelease()
*/
public boolean supportsAggressiveRelease()
{
return true;
}
/**
* Inject a DataSource into this connection provider. Must be provided
* before {@link MyConnectionProvider#configure(Properties)} is invoked
* if the DataSource is not being provided via JNDI.
*
* @param dataSource The dataSource to inject.
*/
public void setDataSource(DataSource dataSource)
{
if (dataSource != null)
{
LOGGER.info("Using injected DataSource");
}
this.dataSource = dataSource;
}
/**
* Set the user name to be used for connections retrieved by the current
* thread, when {@link #getConnection()} is called.
*
* @param userName the user name to use.
*/
public static final void setUserName(String userName)
{
MyConnectionProvider.USER_NAME.set(userName);
}
/**
* Set the password to be used for connections retrieved by the current
* thread, when {@link #getConnection()} is called.
*
* @param password the password to use.
*/
public static final void setPassword(String password)
{
MyConnectionProvider.PASSWORD.set(password);
}
/*Refactored - stub methods added for isWrappableAs and unwrap*/
@Override
public boolean isUnwrappableAs(Class arg0)
{
// TODO Auto-generated method stub
return false;
}
@Override
public <T> T unwrap(Class<T> arg0)
{
// TODO Auto-generated method stub
return null;
}
}
我可以编译 ConnectionProvider,但是我在运行时在 getConnection() 方法中读取的行处抛出了一个空指针异常
conn = lastMaster.getConnection(userName, password);
初始化lastMaster变量的逻辑在configure(props)方法中。然而这个方法没有被调用 - 我认为这就是问题所在。
我注意到 ConnectionProvider 接口(interface)类在 Hibernate 3 和 Hibernate 4 之间发生了显着变化 - 值得注意的是 .configure(props) 方法不再需要,所以我认为无论用于调用 .configure(props) 方法都不再需要这样做的时间更长。
我当前在配置方法中有很多逻辑,因此我假设我的自定义 ConnectionProvider 类无法正常工作是因为它不再像以前那样使用。
有人可以强调一下将自定义 ConnectionProvider 从 Hibernate 3 迁移到 Hibernate 4.3.10 所需的步骤,特别是用于在 configure() 方法中处理的逻辑,或者指出任何可以解释这一点的文档吗?
最佳答案
可能已经晚了,但我遇到了同样的问题,但在查看 <a href="https://forums.hibernate.org/viewtopic.php?p=2452561" rel="noreferrer noopener nofollow">TomcatJDBCConnectionProvider</a>
之后实现,然后我意识到你需要实现 <a href="https://docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/service/spi/Configurable.html" rel="noreferrer noopener nofollow">Configurable</a>
除了 <a href="https://docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/service/jdbc/connections/spi/ConnectionProvider.html" rel="noreferrer noopener nofollow">ConnectionProvider</a>
之外的接口(interface)界面
关于java - Hibernate 3 到 Hibernate 4 迁移 - 自定义 ConnectionProvider 实现 configure() 方法不再存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32227744/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!