如何从spring-data mongodb扩展SimpleMongoRepository?

img*_*gr8 5 spring static mongodb spring-data spring-data-mongodb

我正在尝试创建可由所有DAO扩展的BaseDAO接口。该项目在mongodb中使用spring-data。问题是,如果我让所有单独的DAO扩展MongoRepository而不编写一个Implementation类,那么一切工作正常。但是,如果我尝试使用泛型将MongoRepository添加到BaseDAO界面,则该应用程序将无法正常工作,因为实例化SimpleMongoRepository所需的参数为null。这是我到目前为止的代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

UserDAO.java

import com.test.mongodb.User;
import org.springframework.stereotype.Repository;

@Repository
public interface UserDAO extends BaseDAO<User, String> {}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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()));
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当我运行它时,我在BaseDAOImpl中得到了NPE,因为mongoTemplate和EntityInformationCreator均为空。如何加载它们?我还查看了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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并更改了applicationContext.xml:

<mongo:repositories base-package="com.test.mongodb.repo"
                    factory-class="com.test.mongodb.repo.MongoRepoFactoryBean"/>
Run Code Online (Sandbox Code Playgroud)

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

Oli*_*ohm 0

确保遵循参考文档中的说明。这里没有发生自动装配,因为您必须在 MongoRepositoryFactory 中创建存储库基类的实例(应该有另一种方法来重写,我现在还没有想到,我稍后会添加它,但您可能会略过同时是超类的 Javadoc)。一般来说,出于架构原因,字段注入不是一个好主意,注入静态字段更糟糕:)。