简体   繁体   中英

Hibernate and Spring transactions - using private constructors/static factory methods

We have a Hibernate/Spring application that have the following Spring beans:

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

When wiring the application together we get the following error when using private constructors in our hibernate entities:

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

The entities are typical domain objects such as an Employee or the like.

When changing the constructor's visibility modifier to package (or public) the application runs fine and the entities gets stored/loaded in the database. How do we/can we use private constructors/static factory methods with Spring/Hibernate transaction management?

We use Hibernate annotations to map the entities/relationships. No bean definitions are declared in the applicationContext.xml for the domain class that is related to the problem. It is a pojo that should have a static factory method and a private constructor.

How can we make Hibernate (org.springframework.spring-orm.hibernate3 classes i guess) make use of the static factory method instead of the constructor? Or possibly make it call a private constructor if necessary?

Using the spring factory-method configuration would make sense but the entities are not mapped as beans in our applicationContext.xml. They are only annotated with the @Entity annotation for Hibernate persistence.

Hope this edit clearifies (rather than mystifies) the question. :)

While I haven't used Spring, I have used Hibernate in a project which has classes which must either be instantiated by factory methods or through multiple argument constructors.

You can do this through an Interceptor, which is a class which listens in to several key hibernate events, such as when an object needs to be instantiated or when an object is loaded.

To make Hibernate use your own means of instantiating the object, do something like this:

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;
    }
}

I'm a little suprised that you are having issues with Hibernate not instantiating objects with a non visible constructor, considering that it can be worked around with reflection and I haven't had that issue in my project (non of the classes actually have visible constructors). It may be something with Spring. Check which version of hibernate you are using as well.

Do you know about the property "factory-method" ? You can make spring call that method instead of the constructor to instantiate a bean.

I don't think you can make Hibernate (or any external framework) call a private constructor on your objects, unless it's through some javassist or cglib runtime created subclass.

If you want to let Hibernate call your constructor, why don't you just make it public , or package ? Hibernate instantiates your objects by calling the default no-argument constructor. The documentation states your classes must have the default no-arg constructor with package or public visibility. Your classes must not be final because Hibernate creates proxies for them when using associations.

Section 3.2.3.2 of the Spring Reference discusses the few different ways of instantiating beans in Spring.

You're either interested in the static factory or instance factory methods. All sub sections are pretty short. Take a look and see if you have any further questions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM