Управление объектами Spring-Data Cross Store - PullRequest
4 голосов
/ 18 июля 2011

Я хочу использовать Postgres, MongoDB и Neo4j вместе в моем приложении.Я смог настроить их все, однако теперь каждый из моих POJO поддерживается моим графическим узлом, а также документом aspectJ.

Есть ли способ отфильтровать, какие POJO поддерживаются только графическими узлами, а какие только документом??

У меня проблема с сохранением POJO, когда я делаю это более двух раз [sic!] В одном запросе, и я вижу в журнале, что mongo и neo4j пытаются создать множество экземпляров, которые вызываютнекий король тупиков.

Короче говоря:

  1. Есть ли способ отфильтровать сопоставления данных, чтобы настроить pojo "A" для отображения в RDBMS и графе (без документа)и pojo B по документу и графику (без RDBMS)
  2. Существует ли какой-нибудь пример для кросс-магазина приложений на основе данных пружин, который более или менее охватывает мою проблему?
  3. Почему я могу сохранить два экземпляракласса pojo в моем контроллере один за другим, но когда создается третий экземпляр, я могу заметить тупик?

[EDIT]

Что я заметил:

  1. пнgo сторонний конструктор поддерживает аннотации @Entity POJO и я не знаю, как использовать @Entity для отображения POJO для Hibernate, а не в MongoDB
  2. Заморозка, связанная с Neo4j, происходит только при подключении через REST и происходит иногда 3-го, иногда4-го, а иногда и вовсе не бывает.Посмотрите инициализацию контроллера, как это делается. Я пробовал все закомментированные строки безуспешно.
  3. Конфигурация диспетчера транзакций должна быть размещена в правильном месте, в противном случае служба проверки конфигурации Neo4J не будет работать.

[/ EDIT]

Я использую:

  1. Spring 3.0.5
  2. SpringRoo 1.4
  3. Spring-data 1.0
  4. Postgres 9.0 + Hibernate 3.5.5
  5. Neo4j 1.3 удаленно
  6. MongoDB 1.8.2 удаленно
  7. Все БД находятся на одной удаленной машине и отлично работают

[РЕДАКТИРОВАТЬ]

POM ломтики:

<properties>
    <roo.version>1.1.4.RELEASE</roo.version>
    <spring.version>3.0.5.RELEASE</spring.version>
    <aspectj.version>1.6.11</aspectj.version>
    <slf4j.version>1.6.1</slf4j.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring-security.version>3.0.5.RELEASE</spring-security.version>
    <jackson.version>1.8.0</jackson.version>
    <spring.data.mongodb.version>1.0.0.M2</spring.data.mongodb.version>
    <spring.data.graph.version>1.0.0.RELEASE</spring.data.graph.version>
    <spring.data.commons.version>1.0.0.RELEASE</spring.data.commons.version>
</properties>
    ...
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j</artifactId>
        <version>${spring.data.graph.version}</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb-cross-store</artifactId>
        <version>${spring.data.mongodb.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
        <version>${spring.data.mongodb.version}</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j-rest</artifactId>
        <version>${spring.data.graph.version}</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-commons-core</artifactId>
        <version>${spring.data.commons.version}</version>
        <scope>compile</scope>
    </dependency>

  ....
  <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.0</version>
            <dependencies>
                <!-- NB: You must use Maven 2.0.9 or above or these are ignored (see 
                    MNG-2972) -->
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjrt</artifactId>
                    <version>${aspectj.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjtools</artifactId>
                    <version>${aspectj.version}</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <outxml>true</outxml>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-aspects</artifactId>
                    </aspectLibrary>
                                            <aspectLibrary>
                        <groupId>org.springframework.data</groupId>
                        <artifactId>spring-data-neo4j</artifactId>
                    </aspectLibrary>
                    <aspectLibrary>
                        <groupId>org.springframework.data</groupId>
                        <artifactId>spring-data-mongodb-cross-store</artifactId>
                    </aspectLibrary>

                </aspectLibraries>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>

POJO:

@NodeEntity
@RooToString
@RooJavaBean
public class DElement {

@Indexed
private Long id;

@RelatedTo(direction=Direction.BOTH, elementClass=DRegion.class, type="SUBELEMENT_OF")
private Set<DElement> childElements = new HashSet<DElement>();

@Indexed(indexName = "delement-name", fulltext=true)
private String name;    



@Transactional
public void addChild(DElementchild child)
{
    this.childElements.add(child);
}

}

Контроллер (с загрузкой):

    @Controller
    @RequestMapping(value="/DElements")
    public class DElementsController {

        DElementRepository DElementRepository;

        GraphDatabaseContext gdbc;

        @Autowired
        public DElementsController(DElementRepository DElementRepository, GraphDatabaseContext gdbc)
        {
            this.DElementRepository = DElementRepository;
            this.gdbc = gdbc;
            this.initElements();
        }

        @Transactional
        private void initElements()
        {
            try
            {
                DElementRepository.deleteAll();

            } 
            catch (Exception e) {} finally{}

            //Transaction txn = gdbc.beginTx();

            referenceNode.createRelationshipTo(allElements.getPersistentState(), myRelation);

            DElement naElements = new DElement().persist();
            naElements.setName("1");
            allElements.addChild(naElements);

            DElement saElements = new DElement().persist();
            saElements.setName("2");
            allElements.addChild(saElements);               

            DElement euElements = new DElement().persist();
            euElements.setName("3");
            allElements.addChild(euElements);

            DElement afElements = new DElement().persist();
            afElements.setName("4");    
            allElements.addChild(afElements);

            DElement asElements = new DElement().persist();
            asElements.setName("5");    
            allElements.addChild(asElements);

            DElement auElements = new DElement().persist();
            auElements.setName("6");
            allElements.addChild(auElements);


            //txn.success();
            //txn.finish();

        }
    }

applicationContext.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xmlns:graph="http://www.springframework.org/schema/data/graph"
    xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/data/graph http://www.springframework.org/schema/data/graph/datagraph-1.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:property-placeholder location="classpath*:META-INF/spring/*.properties" />
    <context:spring-configured />
    <bean id="validator"
        class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

    <context:component-scan base-package="com.foobar">
        <context:exclude-filter expression=".*_Roo_.*"
            type="regex" />
        <context:exclude-filter expression="org.springframework.stereotype.Controller"
            type="annotation" />
    </context:component-scan>
    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/foobar" />




    <mongo:mongo host="${foobar.mongodb.addr}" port="27017" />
    <mongo:mapping-converter base-package="com.foobar.lib.model.mongo"/>

    <bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
        <constructor-arg name="mongo" ref="mongo" />
        <constructor-arg name="databaseName" value="foobar" />
        <constructor-arg name="defaultCollectionName" value="basecoll" />
    </bean>

    <bean class="org.springframework.data.document.mongodb.MongoExceptionTranslator" />

    <!-- Mongo cross-store aspect config -->
    <bean
        class="org.springframework.data.persistence.document.mongo.MongoDocumentBacking"
        factory-method="aspectOf">
        <property name="changeSetPersister" ref="mongoChangeSetPersister" />
    </bean>
    <bean id="mongoChangeSetPersister"
        class="org.springframework.data.persistence.document.mongo.MongoChangeSetPersister">
        <property name="mongoTemplate" ref="mongoTemplate" />
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>


    <bean 
        id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
        destroy-method="shutdown" >
        <constructor-arg index="0" value="c:/neo4j/data/foobar" />
    </bean>
<!--  REST DOESNT WORK FOR THE MOMENT
    <bean id="graphDatabaseService" class="org.springframework.data.graph.neo4j.rest.support.RestGraphDatabase">
        <constructor-arg value="${foobar.neo4j.reststore}"/>        
    </bean> -->


<!--    <bean id="graphDatabaseContext" class="org.springframework.data.graph.neo4j.support.GraphDatabaseContext">
        <property name="graphDatabaseService" ref="graphDatabaseService"/>
    </bean> -->

    <graph:repositories base-package="com.foobar.data.repositories.neo4j" graph-database-context-ref="graphDatabaseContext"/>


    <graph:config graphDatabaseService="graphDatabaseService" entityManagerFactory="entityManagerFactory" />
    <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" />    

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">     
        <property name="dataSource" ref="dataSource" />
    </bean> 
</beans>

[/ EDIT]

1 Ответ

4 голосов
/ 22 июля 2011

Некоторые общие замечания.

Вам нужно только передавать entityManagerFactory в Spring Data Graph, если вы хотите использовать кросс-хранилище Graph-JPA. Пример можно найти здесь . Если вы это сделаете, то вам также следует включить флаг part = true в ваших POJO, которые вы хотите использовать в настройке кросс-магазина.

Кросс-хранилище графа данных Spring и кросс-хранилище данных Spring MongoDB работают по-разному в том, как они взаимодействуют с JPA, SDG работает со стороны POJO графика, когда при сохранении или загрузке сущностей они (повторно) подключаются к своей сущности JPA (через @ Идентификатор поля).

С другой стороны, Spring Data MongoDB использует AspectJ для дополнения некоторых методов EntityManager для включения событий жизненного цикла для базы данных документов.

В настоящее время нет истории интеграции MongoDB и Neo4j. Но поскольку мы, руководители обоих проектов, живем в одном городе и тесно сотрудничаем, я думаю, что это должно быть выполнимо.

Было бы замечательно, если бы вы могли поделиться где-нибудь с нами полным кодом вашего проекта, либо на github (это также может быть частное хранилище [мой идентификатор github - "jexp", либо для почты или дропбокса). Так что мы можем копаться прямо в него.

На ваши вопросы:

  • graph + rdmbs - это все сущности, которые имеют частичное = true, и вы должны иметь аннотации @Entity в своем POJO
  • Я не уверен, как правильно настроено постоянство моно-кросс-магазина
  • обычно это должно быть настроено через persistence.xml, в какие хранилища отображается сущность?
  • т.е. возможно, нам следует разработать механизм, который говорит, что настраивает файл persistence.xml для каждого магазина, который хочет взаимодействовать с EntityManager / JPA / RDMBS
  • Возможно, это также работает, определяя двух менеджеров сущностей, один для графа, а другой для Монго?
  • сначала вы должны запустить его во встроенном режиме neo4j, а позже заглянуть на удаленный сервер (REST) ​​
  • вам, вероятно, следует обновить Spring Data Graph до 1.1.M2, Neo4j до 1.4 и AspectJ до 1.6.12.M1

Пожалуйста, свяжитесь лично, чтобы мы могли решить все проблемы и найти хорошее решение.

...