2013-01-15 41 views
4

我正在尝试创建可由所有DAO扩展的BaseDAO接口。该项目使用mongodb的spring数据。问题是,如果我让所有单独的DAO扩展MongoRepository并且不写一个Implementation类,那么一切正常。但是,如果我尝试将MongoRepository添加到带有泛型的BaseDAO接口,则应用程序不再工作,因为实例化SimpleMongoRepository所需的参数为空。这是我的代码至今:如何从spring-data mongodb扩展SimpleMongoRepository?

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

所以,当我运行它,我得到了BaseDAOImpl因为NPE mongoTemplate和entityInformationCreator都是nul湖我如何加载它们?我还查看了Spring MongoDB参考文档,但它主要说遵循其他类型存储库的文档。我能在网上找到的唯一东西就是创建一个工厂bean。于是,我与尝试,以及:

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

,并改变了applicationContext.xml的有:

<mongo:repositories base-package="com.test.mongodb.repo" 
        factory-class="com.test.mongodb.repo.MongoRepoFactoryBean"/> 

但是,这并不工作。我也尝试过使用JavaConfig,但我不知道如何在使用注释进行配置时设置工厂类。我究竟做错了什么? SimpleMongoRepository不带默认构造函数。注入静态字段是否存在问题?

回答

0

确保您按照reference documentation中的说明操作。这里没有自动装配发生,因为您必须在MongoRepositoryFactory中创建存储库基类的实例(应该有另一种方法来覆盖我现在没有记住的内容,稍后我会添加它,但是您可以略过超级'Javadoc在此期间)。一般来说,由于体系结构的原因,现场注入不是一个好主意,注入静态域更糟糕:)。

+1

不是在' – imgr8

+0

对不起,我只是浏览了一下你的XML配置文件,并认为是这样,工厂配置似乎已经被流出文本字段的代码覆盖了。改编我的答案。 –

2

参考文档已过时,并未反映spring-data-mongodb 1.1.1.RELEASE上的更改。

我和你有同样的问题,这里是我如何解决它。

请注意,我使用的都是MongoConfig类和应用程序上下文XML,但您确实不需要两者,我只是决定这样做来举例说明它们的用法。

MongoConfig类:(您也可以通过Spring应用程序上下文XML做到这一点)

@Configuration 
public class MongoConfig extends AbstractMongoConfiguration { 
    @Override 
    protected String getDatabaseName() { 
     return "myDb"; 
    } 

    @Override 
    @Bean 
    public Mongo mongo() throws Exception { 
     return new Mongo("localhost"); 
    } 
} 

春天应用程序上下文XML:

<!-- You can also expose the bean as a method in the MongoConfig class --> 
<bean id="mongoRepositoryFactory" class="org.springframework.data.mongodb.repository.support.MongoRepositoryFactory"> 
    <!-- mongoTemplate comes from AbstractMongoConfiguration --> 
    <constructor-arg ref="mongoTemplate" /> 
</bean> 

<context:annotation-config /> 
<context:component-scan base-package="com.example.domain" /> 
<mongo:repositories base-package="com.example.domain.repository" mongo-template-ref="mongoTemplate" /> 

我的资料库/ DAO类:

@Repository 
public class MyBeanDao extends SimpleMongoRepository<MyBean, String> { 

    public MyBeanDao(MongoEntityInformation<MyBean, String> metadata, MongoOperations mongoOperations) { 
     super(metadata, mongoOperations); 
    } 

    @Autowired 
    public MyBeanDao(MongoRepositoryFactory factory, MongoOperations mongoOperations) { 
     this(factory.<MyBean, String>getEntityInformation(MyBean.class), mongoOperations); 
    } 

    ... // more stuff 
} 

我知道这真的很丑,只适用于Java 6,但由于getEntityInformation()的返回类型是完全无界的,因此它或者是ID类型是Serializable而不是实际的ID类型,并执行显式强制转换每次你需要它。

我希望有一个更清洁的方式,但我一直在寻找相当一段时间通过API,甚至源代码,并没有想出一个更好的方法来做到这一点,而没有提出自己的实现一些spring-data-mongodb类。

希望它有帮助。

+0

嗨,我是新的mongodb你能帮我预先感谢你..当我尝试autowire MyBeanDao我得到默认的构造函数错误,所以我如何使用MyBeanDao方法。 –

+0

@Atul你能发布错误信息还是stacktrace? – Russell

0

通过使用<mongo:mapping-converter id="..." base-package="..." />修复了它,并确保将所有持续保留的类标记为@Document注释,即使它们没有自己的集合。

0

post中详细介绍了使用spring-data mongodb为'向所有存储库添加自定义行为'的适当解决方案。

按照上面的帖子中描述的步骤后,你可以有你的任何资料库界面的自定义共享库接口扩展如下

@Repository 
public interface CustomerRepository extends MongoRepository<Customer, String>, 
     WootideRepositoryCustom<Customer, String> { 
} 

在WootideRepositoryImpl提供的实施将是可用CustomerRepository。

它对我来说非常好。

1

我为Spring和MongoDB使用MongoTemplate编写了Spring Web应用程序(MVC)的可扩展数据访问库,但完全避免了自动布线和存储库。它在控制器和数据层之间有松耦合(使用Factory)。您可以在其他域对象可以自动继承的基本实现中添加更多基本数据方法。请参阅https://github.com/rameshpa/spring-mongodb