Comment étendre SimpleMongoRepository de printemps-données mongodb?
Je suis en train de créer un BaseDAO interface qui peut être étendue à tous les DAOs. Le projet utilise printemps-données avec mongodb. Le problème est que si je fais tous les DAOs étendre MongoRepository et de ne pas écrire une Implémentation de la classe, puis tout fonctionne bien. Mais si j'essaie d'ajouter le MongoRepository à la BaseDAO interface avec les médicaments génériques, l'app ne fonctionne plus parce que les paramètres requis pour instancier SimpleMongoRepository sont nulles. C'est le code que j'ai pour l'instant :
BaseDAO.java
import com.test.mongodb.BaseEntity;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.NoRepositoryBean;
import java.io.Serializable;
@NoRepositoryBean
public interface BaseDAO<T extends BaseEntity, ID extends Serializable> extends MongoRepository<T, ID> {
public T getTestObject(ID id);
}
BaseDAOImpl.java
import com.test.mongodb.BaseEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.query.EntityInformationCreator;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;
import org.springframework.data.repository.NoRepositoryBean;
import java.io.Serializable;
@NoRepositoryBean
public class BaseDAOImpl<T extends BaseEntity, ID extends Serializable> extends SimpleMongoRepository<T,
ID> implements BaseDAO<T, ID> {
@Autowired
private static MongoTemplate mongoTemplate;
@Autowired
private static EntityInformationCreator entityInformationCreator;
public BaseDAOImpl(Class<T> type){
super((MongoEntityInformation<T, ID>) entityInformationCreator.getEntityInformation(type), mongoTemplate);
}
@Override
public T getTestObject(ID id){
return findOne(id);
}
}
UserDAO.java
import com.test.mongodb.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserDAO extends BaseDAO<User, String> {}
UserDAOImpl.java
import com.test.mongodb.User;
import org.springframework.stereotype.Repository;
@Repository
public class UserDAOImpl extends BaseDAOImpl<User, String> implements UserDAO {
public UserDAOImpl(){
super(User.class);
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd">
<!-- MongoFactoryBean instance -->
<mongo:mongo host="localhost" port="27017" />
<mongo:db-factory dbname="bank" mongo-ref="mongo" />
<!-- MongoTemplate instance -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<bean id="mappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
<bean id="entityInformationCreator" class="org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator">
<constructor-arg name="mappingContext" ref="mappingContext" />
</bean>
<mongo:repositories base-package="com.test.mongodb.repo"/>
</beans>
App.java
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserRepository userRepository = context.getBean("userRepository", UserRepository.class);
User user = new User("Test User");
userRepository.save(user);
String id = user.getId();
System.out.println(id);
System.out.println(userRepository.getTestObject(user.getId()));
}
}
Donc quand je le lance, j'obtiens un NPE dans BaseDAOImpl parce que les deux la mongoTemplate et la entityInformationCreator sont nulles. Comment puis-je charger? J'ai aussi regardé le Printemps MongoDB document de référence, mais il a surtout dit de suivre la documentation pour d'autres types de référentiels. La seule chose que je pouvais y trouver et à d'autres endroits en ligne était de créer une usine bean. J'ai donc essayé avec ça :
MongoRepoFactoryBean.java
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import java.io.Serializable;
@NoRepositoryBean
public class MongoRepoFactoryBean<T extends MongoRepository<?,?>, ID extends
Serializable> extends MongoRepositoryFactoryBean {
protected RepositoryFactorySupport createRepositoryFactory(Class<T> clazz, MongoTemplate mongoTemplate) {
return new MongoRepoFactory(clazz, mongoTemplate);
}
private static class MongoRepoFactory extends MongoRepositoryFactory {
private Class clazz;
private MongoTemplate mongoTemplate;
public MongoRepoFactory(Class clazz, MongoTemplate mongoTemplate) {
super(mongoTemplate);
this.mongoTemplate = mongoTemplate;
this.clazz = clazz;
}
public Object getTargetRepository() {
return new BaseDAOImpl(clazz);
}
public Class<?> getRepositoryBaseClass() {
return BaseDAOImpl.class;
}
}
}
et changé le applicationContext.xml avec :
<mongo:repositories base-package="com.test.mongodb.repo"
factory-class="com.test.mongodb.repo.MongoRepoFactoryBean"/>
Mais cela ne fonctionne pas non plus. J'ai essayé avec JavaConfig ainsi, mais je ne sais pas comment définir l'usine de la classe lors de la configuration à l'aide d'annotations. Ce que je fais mal? SimpleMongoRepository ne vient pas avec un constructeur par défaut. Est le problème de l'injection de champs statiques?
OriginalL'auteur imgr8 | 2013-01-15
Vous devez vous connecter pour publier un commentaire.
La documentation de référence est dépassée, ne reflète pas les modifications sur le printemps de données mongodb 1.1.1.La LIBÉRATION.
J'ai eu le même problème que vous, voici comment j'solution de contournement-ed.
Remarque que je suis en utilisant à la fois MongoConfig de la classe et de l'application de contexte XML, mais vous n'avez pas vraiment besoin des deux, j'ai juste décidé de le faire de cette façon de donner des exemples de leur utilisation.
MongoConfig classe: (Vous pouvez également le faire via le printemps app contexte XML)
Printemps App Contexte XML:
Mon repository/classe dao:
Je sais que c'est vraiment moche et ne fonctionne que sur la version 6 de Java, mais depuis que le type de retour de getEntityInformation() est totalement illimité, c'est ça ou l'ID est de type être Sérialisable au lieu de votre type d'ID et de faire le cast explicite à chaque fois que vous en avez besoin.
Je souhaite qu'il y avait une manière plus propre mais j'ai été la recherche de quelques temps par le biais de l'API, et même le code source et je n'ai pas trouvé une meilleure façon de le faire sans venir avec votre propre mise en œuvre de certaines printemps de données mongodb classes.
Espère que cela aide.
Pouvez-vous poster le message d'erreur ou stacktrace?
Je reçois
NoSuchBeanDefenitionException
au constructeur si j'ai un dbFactory dans ma config xmlOriginalL'auteur Russell
J'ai écrit un extensible bibliothèque d'accès aux données pour le Printemps et MongoDB pour le Printemps des applications web (MVC) à l'aide de MongoTemplate mais totalement en évitant l'auto-câblage et de Référentiel. Il a le couplage lâche (à l'aide de l'Usine) entre le Contrôleur et la couche de données. Vous pouvez ajouter plus de la base de données des méthodes à la base de la mise en œuvre que d'autres objets de domaine peut hériter automatiquement. Voir https://github.com/rameshpa/spring-mongodb
OriginalL'auteur rameshpa
Assurez-vous de suivre les instructions dans le la documentation de référence. Il n'y a pas permettra à l'autowiring de passe que vous avez pour créer l'instance du référentiel de la classe de base dans votre MongoRepositoryFactory (il devrait y avoir une autre méthode pour remplacer la qui je n'ai pas à l'esprit maintenant, je vais ajouter que plus tard, mais vous pouvez écumer la super classe " Javadoc dans l'intervalle). En général, le champ d'injection n'est pas une bonne idée pour des raisons d'architecture et d'injecter dans les champs statiques est encore pire :).
<mongo:repositories base-package="com.test.mongodb.repo" factory-class="com.test.mongodb.repo.MongoRepoFactoryBean"/>
Désolé, je viens écrémé à votre configuration XML et pensais que c'était elle, la configuration de l'usine semble avoir été arrondis par le code, sortant du champ de texte. Adapté ma réponse.
OriginalL'auteur Oliver Drotbohm
Fixe en utilisant
<mongo:mapping-converter id="..." base-package="..." />
, et fait en sorte de marque de tous mes persisté classes avec@Document
annotation, même s'ils ne disposent pas de leur propre collection.OriginalL'auteur Russell
Solution appropriée pour 'l'Ajout de comportement à tous les référentiels" à l'aide de printemps de données mongodb est détaillée dans ce post.
Après avoir suivi les étapes décrites dans le post ci-dessus, vous pouvez avoir tout de votre référentiel d'interface pour étendre la coutume-partagé-référentiel de l'interface comme ci-dessous
La mise en œuvre prévues dans WootideRepositoryImpl sera disponible dans CustomerRepository.
Il a travaillé très bien pour moi.
OriginalL'auteur Subhu.rys