【问题标题】:Hibernate and Spring transactions - using private constructors/static factory methodsHibernate 和 Spring 事务 - 使用私有构造函数/静态工厂方法
【发布时间】:2010-09-25 02:15:56
【问题描述】:

我们有一个具有以下 Spring bean 的 Hibernate/Spring 应用程序:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" />

在将应用程序连接在一起时,在我们的休眠实体中使用私有构造函数时会出现以下错误:

Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No visible constructors in class 'ourclass'

实体是典型的域对象,例如员工等。

将构造函数的可见性修饰符更改为包(或公共)时,应用程序运行良好,实体被存储/加载到数据库中。我们如何/我们可以在 Spring/Hibernate 事务管理中使用私有构造函数/静态工厂方法?

我们使用 Hibernate 注释来映射实体/关系。在 applicationContext.xml 中没有为与问题相关的域类声明任何 bean 定义。它是一个 pojo,应该有一个静态工厂方法和一个私有构造函数。

我们怎样才能让 Hibernate(我猜是 org.springframework.spring-orm.hibernate3 类)使用静态工厂方法而不是构造函数?或者如果需要的话可能让它调用一个私有构造函数?

使用 spring factory-method 配置是有意义的,但实体没有映射为我们的 applicationContext.xml 中的 bean。它们仅使用 @Entity 注释进行注释以实现 Hibernate 持久性。

希望这次编辑能够澄清(而不是神秘化)这个问题。 :)

【问题讨论】:

    标签: java hibernate spring transactions


    【解决方案1】:

    你知道“工厂方法”这个属性吗?您可以让 spring 调用该方法而不是构造函数来实例化一个 bean。

    【讨论】:

    • 您能否详细说明如何做到这一点,以便 Hibernate 事务管理器使用工厂方法?引发异常的是事务管理器。我们使用 Hibernate 注释来映射实体/关系。
    • 你能发布你的配置文件,以及类的相关部分吗?
    • 在实例化 Spring bean 时使用 factory-method。在这种情况下,问题似乎在于 Hibernate bean 的实例化。
    【解决方案2】:

    我认为你不能让 Hibernate(或任何外部框架)在你的对象上调用私有构造函数,除非它是通过一些 javassist 或 cglib 运行时创建的子类。

    如果你想让 Hibernate 调用你的构造函数,为什么不直接使用publicpackage? Hibernate 通过调用默认的无参数构造函数来实例化您的对象。文档说明您的类必须具有默认的无参数构造函数,该构造函数具有包或公共可见性。您的类不能是 final,因为 Hibernate 在使用关联时会为它们创建代理。

    【讨论】:

    • 好吧,我不想要公共或包(包实际上还可以,但不是很好)构造函数,因为它使 API 不那么干净。我希望在从其他类实例化类时使用静态工厂方法(或工厂)。如果 hibernate 也可以使用静态工厂方法,那将是理想的。
    【解决方案3】:

    Section 3.2.3.2 of the Spring Reference 讨论了在 Spring 中实例化 bean 的几种不同方法。

    您要么对静态工厂方法感兴趣,要么对实例工厂方法感兴趣。所有子部分都很短。看看您是否还有其他问题。

    【讨论】:

    • 感谢您的否决票,但没有说明原因。最初的问题是我引用的静态工厂调用的用法。
    【解决方案4】:

    虽然我没有使用 Spring,但我在一个项目中使用了 Hibernate,该项目具有必须通过工厂方法或通过多个参数构造函数实例化的类。

    您可以通过一个拦截器来做到这一点,它是一个侦听几个关键休眠事件的类,例如何时需要实例化对象或加载对象。

    要让 Hibernate 使用您自己的方法来实例化对象,请执行以下操作:

    public class MyInterceptor extends EmptyInterceptor {
    
        public Object instantiate(String entityName, EntityMode entityMode, Serializable id) {
            if(entityName.equals(Foo.class.getName())
                 return Foo.create();
            return null;
        }
    }
    

    考虑到它可以通过反射来解决,我在我的项目中没有遇到这个问题(非类实际上有可见的构造函数)。这可能与Spring有关。检查您正在使用的休眠版本。

    【讨论】:

    • 由于是带有 org.springframework.spring-orm.hibernate 的 Hibernate 类导致了问题,我非常确信它与 Spring 有关。 AnnotationSessionFactoryBean 是一个嫌疑犯......
    猜你喜欢
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多