2013-01-15 40 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