【问题标题】:Casting java.sql.Connection to com.mysql.jdbc.Connection将 java.sql.Connection 转换为 com.mysql.jdbc.Connection
【发布时间】:2011-12-20 21:57:13
【问题描述】:

我的数据库使用 MySQL,我使用 hibernate 作为 ORM 框架。我有一个实例需要访问 MySQL Connection 对象。我使用以下代码来获取java.sql.Connection 对象:

getHibernateTemplate().getSessionFactory().getCurrentSession().connection();

但是,当我尝试将其强制转换为 (com.mysql.jdbc.Connection) 对象时,出现以下异常:

java.lang.ClassCastException: $Proxy50 cannot be cast to com.mysql.jdbc.Connection

奇怪的是,如果我这样做conn.getClass().getName(),返回的类类型是“$Proxy50”而不是“java.sql.Connection”或其他一些有意义的类型。

从 Hibernate 获取特定于供应商的Connection 对象的正确方法是什么? (我正在尝试读取 MySQL 系统属性)。为什么我上面的例子不起作用?

【问题讨论】:

  • 不确定 Spring 的 HibernateTemplate 是如何发挥作用的,但请尝试Connection#unwrap()
  • 这样做要非常小心。 “原始” JDBC 连接通常位于几个不同的类层下,这些类都实现了连接。最常见的情况是连接池将添加的层,这样当您“关闭”连接时,您真正要做的就是将其返回到池中。如果您对这些层之一正在跟踪的原始连接进行某些操作,则可能会出现问题。绝对确定你需要这样做,而不是通过其他方式实现目标。
  • @BalusC - 好主意。我试过了,但是我的 Apache DBCP 连接池程序版本没有实现 unwrap 方法。当我尝试它时,我得到了以下异常: java.lang.AbstractMethodError: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.unwrap(Ljava/lang/ClassLjava/lang/Object;
  • @rfeak - 我只是想读取 MySQL allowNanAndInf 属性的值(它确定双字段中是否允许 NaN 值)。我不打算对供应商 MySQL Connection 对象执行任何查询或插入/更新。
  • DBCP 确实不符合 JDBC4。好吧,如果可以,请更换它。无论如何,这是一个可怕的游泳池。另见stackoverflow.com/questions/520585/…

标签: java hibernate casting


【解决方案1】:

通常,您不需要访问具体的Connection 实现。

但如果您真的非常需要,这里有一个解释:$Proxy40 意味着它是一个 JDK 动态代理。 Spring倾向于创建这些。如果你的是spring创建的,那么,你可以通过以下方式获取真实对象:

Advised advised = (Advised) connection;
Connection conn = (Connection) advised.getTargetSource().getTarget();

如果代理不涉及 spring,您应该可以按照 BalusC 的建议调用 Connection.unwrap(..)(无论哪种方式,您都应该可以这样做)

【讨论】:

  • 我正在使用 Spring,所以我尝试了您的代码示例并得到以下异常:java.lang.ClassCastException: $Proxy50 cannot be cast to org.springframework.aop.framework.Advised
  • 那么也许代理还没有被spring创建。你试过 .unwrap(..) 方法了吗?
【解决方案2】:

获取供应商特定连接的正确方法是什么 来自 Hibernate 的对象?

视情况而定。

我已经像这样成功地解开了 Proxy 的包装。 How to unwrap the original object from a dynamic proxy

虽然有点可怕,但如果可以的话,请避免它。

【讨论】:

    【解决方案3】:

    com.mysql.jdbc.Connection 实现java.sql.Connection 接口。因此,当您创建 com.mysql.jdbc.Connection 对象时也是 java.sql.Connection 对象。所以你不能在那里进行操作,因为返回的对象是java.sql.Connection 而不是com.mysql.jdbc.Connection

    【讨论】:

    • 你需要阅读downcasting,这正是这种操作。这是危险的,因为与原始海报问题一样,如果您不知道连接的确切类型,您最终可能会得到ClassCastException。在这种情况下,对象是java.sql.Connection 的类型,它恰好不是com.mysql.jdbc.Connection
    猜你喜欢
    • 2014-02-12
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    相关资源
    最近更新 更多