java - ejemplo - spring mvc 4 tutorial español
Transacciones de Hibernate y Spring: uso de constructores privados/métodos de fábrica estáticos (4)
Tenemos una aplicación Hibernate / Spring que tiene los siguientes beans de Spring:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" />
Al cablear la aplicación, obtenemos el siguiente error al usar constructores privados en nuestras entidades hibernadas:
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No visible constructors in class ''ourclass''
Las entidades son objetos de dominio típicos, como un empleado o similar.
Al cambiar el modificador de visibilidad del constructor al paquete (o público), la aplicación se ejecuta correctamente y las entidades se almacenan / cargan en la base de datos. ¿Cómo podemos / podemos usar constructores privados / métodos de fábrica estáticos con la gestión de transacciones Spring / Hibernate?
Usamos anotaciones de Hibernate para mapear las entidades / relaciones. No se declaran definiciones de bean en applicationContext.xml para la clase de dominio relacionada con el problema. Es un pojo que debe tener un método de fábrica estático y un constructor privado.
¿Cómo podemos hacer que Hibernate (clases de org.springframework.spring-orm.hibernate3, supongo) haga uso del método de fábrica estático en lugar del constructor? ¿O posiblemente lo haga llamar a un constructor privado si es necesario?
Usar la configuración del método de fábrica de primavera tendría sentido, pero las entidades no están mapeadas como beans en nuestro applicationContext.xml. Solo están anotados con la anotación @Entity para la persistencia de Hibernate.
Espero que esta edición aclare (en lugar de mistificar) la pregunta. :)
¿Conoces la propiedad "fábrica-método"? Puede hacer una llamada de primavera a ese método en lugar del constructor para crear instancias de un bean.
No creo que pueda hacer que Hibernate (o cualquier marco externo) llame a un constructor privado en sus objetos, a menos que sea a través de una subclase creada por javassist o cglib runtime.
Si quieres que Hibernate llame a tu constructor, ¿por qué no lo haces public
o en package
? Hibernate crea una instancia de sus objetos llamando al constructor predeterminado sin argumento. La documentación indica que sus clases deben tener el constructor no-arg predeterminado con paquete o visibilidad pública. Tus clases no deben ser final
porque Hibernate crea proxies para ellas cuando usan asociaciones.
La Sección 3.2.3.2 de la Referencia de Primavera discute las pocas formas diferentes de instanciar los frijoles en la primavera.
También está interesado en la fábrica estática o en los métodos de fábrica de instancias. Todas las subsecciones son bastante cortas. Eche un vistazo y vea si tiene más preguntas.
Si bien no he usado Spring, he usado Hibernate en un proyecto que tiene clases que deben ser instanciadas por métodos de fábrica o por medio de múltiples constructores de argumentos.
Puede hacerlo a través de un Interceptor, que es una clase que escucha varios eventos clave de hibernación, como cuando un objeto necesita ser instanciado o cuando se carga un objeto.
Para hacer que Hibernate use su propio medio para crear instancias del objeto, haga algo como esto:
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;
}
}
Estoy un poco sorprendido de que tengas problemas con Hibernate sin crear instancias de objetos con un constructor no visible, teniendo en cuenta que se puede trabajar con reflexión y no he tenido ese problema en mi proyecto (ninguna de las clases tiene realmente visible constructores). Puede ser algo con Spring. Comprueba también qué versión de hibernación estás usando.