2008-12-03 7 views
2

Nous avons une application Hibernate/Spring qui ont les suivants grains de printemps:Hibernate et les transactions de printemps - en utilisant les constructeurs privés/méthodes d'usine statiques

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

Lors du câblage de l'application, ensemble, nous obtenons l'erreur suivante lors de l'utilisation des constructeurs privés dans nos entités d'hibernation:

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

Les entités sont des objets de domaine typiques tels qu'un employé ou similaire.

Lors d'un changement de modificateur de visibilité du constructeur à forfait (ou public) l'application fonctionne bien et les entités est stockée/chargé dans la base de données. Comment pouvons-nous/pouvons-nous utiliser des constructeurs privés/des méthodes d'usine statiques avec la gestion des transactions Spring/Hibernate?

Nous utilisons des annotations Hibernate pour cartographier les entités/relations. Aucune définition de bean n'est déclarée dans le fichier applicationContext.xml pour la classe de domaine liée au problème. C'est un pojo qui devrait avoir une méthode d'usine statique et un constructeur privé.

Comment pouvons-nous faire Hibernate (org.springframework.spring-orm.hibernate3 classes je suppose) faire usage de la méthode usine statique au lieu du constructeur? Ou peut-être faire appel à un constructeur privé si nécessaire?

En utilisant la configuration de printemps usine méthode aurait du sens, mais les entités ne sont pas cartographiés comme les haricots dans notre applicationContext.xml. Ils sont uniquement annotés avec l'annotation @Entity pour la persistance Hibernate.

espère que cette édition clearifies (plutôt que mystifie) la question. :)

Répondre

5

Bien que je ne l'ai pas utilisé Spring, j'ai utilisé Hibernate dans un projet qui a des classes qui doivent soit être instanciés par des méthodes d'usine ou par plusieurs constructeurs d'arguments.

Vous pouvez le faire via un intercepteur, qui est une classe qui écoute plusieurs événements de mise en veille prolongée, comme lorsqu'un objet doit être instancié ou lorsqu'un objet est chargé.

Pour faire Hibernate utiliser vos propres moyens d'instancier l'objet, faire quelque chose comme ceci:

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

Je suis un peu surpris de voir que vous rencontrez des problèmes avec Hibernate pas instanciation des objets avec un constructeur non visible, Considérant qu'il peut être travaillé avec réflexion et je n'ai pas eu ce problème dans mon projet (pas de classes ont réellement des constructeurs visibles). Ce peut être quelque chose avec le printemps. Vérifiez également la version d'Hibernate que vous utilisez.

+0

Puisque ce sont les classes Hibernate avec org.springframework.spring-orm.hibernate qui causent des problèmes, je suis assez convaincu que c'est lié à Spring. Le AnnotationSessionFactoryBean est un suspect ... –

1

Connaissez-vous la propriété "factory-method"? Vous pouvez faire appel au printemps à cette méthode au lieu du constructeur pour instancier un bean.

+0

Pourriez-vous élaborer un peu sur la façon de faire cela afin que le gestionnaire de transactions Hibernate utilise la méthode d'usine? C'est le gestionnaire de transactions qui lève l'exception. Et nous utilisons les annotations Hibernate pour mapper les entités/relations. –

+0

Pouvez-vous publier votre fichier de configuration, avec les parties pertinentes des classes? – BraveSirFoobar

+1

La méthode usine est utilisée lors de l'instanciation des haricots Spring. Dans ce cas, il semble que le problème soit l'instanciation des beans Hibernate. – Guillaume

0

Je ne pense pas que vous pouvez faire Hibernate (ou tout autre cadre externe) appeler un constructeur privé sur vos objets, à moins que ce soit par une exécution javassist ou sous-classe cglib créé.

Si vous voulez que Hibernate appelle votre constructeur, pourquoi ne pas le faire public ou package? Hibernate instancie vos objets en appelant le constructeur par défaut sans argument. La documentation déclare que vos classes doivent avoir le constructeur par défaut sans argot avec une visibilité de paquet ou publique. Vos classes ne doivent pas être final car Hibernate crée des proxies pour eux lors de l'utilisation d'associations.

+0

Eh bien, je ne veux pas de constructeurs publics ou de paquets (le paquet est en fait correct mais pas gentil) car cela rend l'API moins propre. Je souhaite utiliser une méthode d'usine statique (ou usine) lors de l'instanciation de la classe à partir d'autres classes. Il serait idéal si Hibernate pouvait aussi utiliser une méthode d'usine statique. –

0

Section 3.2.3.2 of the Spring Reference examine les différentes façons de instancier les haricots au printemps.

Vous êtes intéressé par les méthodes d'usine statique ou d'usine d'instance. Toutes les sous-sections sont assez courtes. Jetez un coup d'oeil et voyez si vous avez d'autres questions.

+0

Merci pour le vote vers le bas sans le commentaire quant à pourquoi. La question initiale était l'utilisation des appels d'usine statiques, que je référenais. –

Questions connexes