- 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/
背景: 我最近一直在使用 JPA,我为相当大的关系数据库项目生成持久层的轻松程度给我留下了深刻的印象。 我们公司使用大量非 SQL 数据库,特别是面向列的数据库。我对可能对这些数据库使用 JPA 有一
我已经在我的 maven pom 中添加了这些构建配置,因为我希望将 Apache Solr 依赖项与 Jar 捆绑在一起。否则我得到了 SolarServerException: ClassNotF
interface ITurtle { void Fight(); void EatPizza(); } interface ILeonardo : ITurtle {
我希望可用于 Java 的对象/关系映射 (ORM) 工具之一能够满足这些要求: 使用 JPA 或 native SQL 查询获取大量行并将其作为实体对象返回。 允许在行(实体)中进行迭代,并在对当前
好像没有,因为我有实现From for 的代码, 我可以转换 A到 B与 .into() , 但同样的事情不适用于 Vec .into()一个Vec . 要么我搞砸了阻止实现派生的事情,要么这不应该发
在 C# 中,如果 A 实现 IX 并且 B 继承自 A ,是否必然遵循 B 实现 IX?如果是,是因为 LSP 吗?之间有什么区别吗: 1. Interface IX; Class A : IX;
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在阅读标准haskell库的(^)的实现代码: (^) :: (Num a, Integral b) => a -> b -> a x0 ^ y0 | y0 a -> b ->a expo x0
我将把国际象棋游戏表示为 C++ 结构。我认为,最好的选择是树结构(因为在每个深度我们都有几个可能的移动)。 这是一个好的方法吗? struct TreeElement{ SomeMoveType
我正在为用户名数据库实现字符串匹配算法。我的方法采用现有的用户名数据库和用户想要的新用户名,然后检查用户名是否已被占用。如果采用该方法,则该方法应该返回带有数据库中未采用的数字的用户名。 例子: “贾
我正在尝试实现 Breadth-first search algorithm , 为了找到两个顶点之间的最短距离。我开发了一个 Queue 对象来保存和检索对象,并且我有一个二维数组来保存两个给定顶点
我目前正在 ika 中开发我的 Python 游戏,它使用 python 2.5 我决定为 AI 使用 A* 寻路。然而,我发现它对我的需要来说太慢了(3-4 个敌人可能会落后于游戏,但我想供应 4-
我正在寻找 Kademlia 的开源实现C/C++ 中的分布式哈希表。它必须是轻量级和跨平台的(win/linux/mac)。 它必须能够将信息发布到 DHT 并检索它。 最佳答案 OpenDHT是
我在一本书中读到这一行:-“当我们要求 C++ 实现运行程序时,它会通过调用此函数来实现。” 而且我想知道“C++ 实现”是什么意思或具体是什么。帮忙!? 最佳答案 “C++ 实现”是指编译器加上链接
我正在尝试使用分支定界的 C++ 实现这个背包问题。此网站上有一个 Java 版本:Implementing branch and bound for knapsack 我试图让我的 C++ 版本打印
在很多情况下,我需要在 C# 中访问合适的哈希算法,从重写 GetHashCode 到对数据执行快速比较/查找。 我发现 FNV 哈希是一种非常简单/好/快速的哈希算法。但是,我从未见过 C# 实现的
目录 LRU缓存替换策略 核心思想 不适用场景 算法基本实现 算法优化
1. 绪论 在前面文章中提到 空间直角坐标系相互转换 ,测绘坐标转换时,一般涉及到的情况是:两个直角坐标系的小角度转换。这个就是我们经常在测绘数据处理中,WGS-84坐标系、54北京坐标系
在软件开发过程中,有时候我们需要定时地检查数据库中的数据,并在发现新增数据时触发一个动作。为了实现这个需求,我们在 .Net 7 下进行一次简单的演示. PeriodicTimer .
二分查找 二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。
我是一名优秀的程序员,十分优秀!