Управление объектами Spring-Data Cross Store
Я хочу использовать Postgres, MongoDB и Neo4j вместе в моем приложении. Я смог сконфигурировать их все, однако теперь каждый из моих POJO поддерживается моим графическим узлом, а также документом aspectJ.
Есть ли способ отфильтровать, какие POJO поддерживаются только graphNodes, а какие только документом?
У меня есть проблема с сохранением POJO, когда я делаю это более двух раз [sic!] В одном запросе, и я вижу в журнале, что оба mongo и neo4j пытаются создать множество экземпляров, которые вызывают какой-то король тупиков.
Короче говоря:
- Есть ли способ отфильтровать сопоставления данных для настройки pojo "A" для отображения с помощью СУБД и графика (без документа) и pojo B с помощью документа и графика (без СУРБД)
- Есть ли пример для кросс-магазина приложений, основанных на данных пружины, который более или менее охватывает мою проблему?
- Почему я могу сохранить два экземпляра класса pojo в моем контроллере один за другим, но когда создается третий экземпляр, я могу заметить тупик?
[РЕДАКТИРОВАТЬ]
Что я заметил:
- Mongo aspectj builder поддерживает @Entity аннотированные POJO и я не знаю, как использовать @Entity для отображения POJO для Hibernate, а не в MongoDB
- Замораживание, связанное с Neo4j, происходит только при подключении через REST и происходит иногда 3-го, иногда 4-го, а иногда вообще не происходит. Посмотрите инициализацию контроллера, как это делается. Я попробовал все закомментированные строки безуспешно.
- Конфигурация диспетчера транзакций должна быть размещена в правильном месте, в противном случае служба проверки конфигурации Neo4J не будет работать.
[/РЕДАКТИРОВАТЬ]
Я использую:
- Spring 3.0.5
- SpringRoo 1.4
- Spring-data 1.0
- Postgres 9.0 + Hibernate 3.5.5
- Neo4j 1.3 удаленно
- MongoDB 1.8.2 удаленно
- Все БД находятся на одной удаленной машине и работают нормально
[РЕДАКТИРОВАТЬ]
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>
[/РЕДАКТИРОВАТЬ]
1 ответ
Несколько общих замечаний.
Вам нужно только передать entityManagerFactory в Spring Data Graph, если вы хотите использовать кросс-хранилище Graph-JPA. Пример можно найти здесь. Если вы сделаете это, то вам также следует включить флаг part =true в ваших POJO, которые вы хотите использовать в настройке кросс-магазина.
Кросс-хранилище Spring Data Graph и кросс-хранилище Spring Data MongoDB работают по-разному в том, как они взаимодействуют с JPA, SDG работает со стороны POJO Graph, когда при сохранении или загрузке сущностей они (повторно) подключаются к своей сущности JPA (через поле @Id),
С другой стороны, Spring Data MongoDB использует AspectJ для дополнения некоторых методов EntityManager для включения событий жизненного цикла для базы данных документов.
На данный момент нет истории для интеграции MongoDB и Neo4j. Но поскольку мы, руководители обоих проектов, живем в одном городе и тесно сотрудничаем, я думаю, что это должно быть выполнимо.
Было бы здорово, если бы вы могли поделиться где-нибудь с нами полным кодом вашего проекта, либо на github (это также может быть частное хранилище [мой идентификатор github - "jexp", либо для почты или дропбокса). Чтобы мы могли копаться прямо в этом.
На ваши вопросы:
- graph + rdmbs - это все сущности, которые имеют part =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
Пожалуйста, свяжитесь лично, чтобы мы могли решить все проблемы и найти хорошее решение.