DATAGRAPH-1102 - Apply Spring Data Code Formatting Settings.
This commit applied the Spring Data Code Formatting Settings
37b34a56ce/etc/ide
through the Eclipse Code Formatter for IDEA.
This closes #413.
# Conflicts:
# pom.xml
# spring-data-neo4j/pom.xml
This commit is contained in:
389
pom.xml
389
pom.xml
@@ -1,214 +1,215 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>4.2.14.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>4.2.14.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data Neo4j</name>
|
||||
<description>Neo4j support for Spring Data</description>
|
||||
<url>http://projects.spring.io/spring-data-neo4j</url>
|
||||
<name>Spring Data Neo4j</name>
|
||||
<description>Neo4j support for Spring Data</description>
|
||||
<url>http://projects.spring.io/spring-data-neo4j</url>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>1.9.14.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>1.9.14.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-data-neo4j</module>
|
||||
<module>spring-data-neo4j-distribution</module>
|
||||
</modules>
|
||||
<modules>
|
||||
<module>spring-data-neo4j</module>
|
||||
<module>spring-data-neo4j-distribution</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-neo4j</dist.id>
|
||||
<springdata.commons>1.13.14.BUILD-SNAPSHOT</springdata.commons>
|
||||
<source.level>1.8</source.level>
|
||||
</properties>
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-neo4j</dist.id>
|
||||
<springdata.commons>1.13.14.BUILD-SNAPSHOT</springdata.commons>
|
||||
<source.level>1.8</source.level>
|
||||
</properties>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>vbickers</id>
|
||||
<name>Vince Bickers</name>
|
||||
<email>vince at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>GMT</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>atg</id>
|
||||
<name>Adam George</name>
|
||||
<email>adam at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>GMT</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>bachmanm</id>
|
||||
<name>Michal Bachman</name>
|
||||
<email>michal at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>GMT</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>lmisquitta</id>
|
||||
<name>Luanne Misquitta</name>
|
||||
<email>luanne at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+5:30</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mangrish</id>
|
||||
<name>Mark Angrish</name>
|
||||
<email>mark at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+11</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>jasperblues</id>
|
||||
<name>Jasper Blues</name>
|
||||
<email>jasper at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+8</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mhunger</id>
|
||||
<name>Michael Hunger</name>
|
||||
<email>michael.hunger at neotechnology.com</email>
|
||||
<organization>Neo Technology</organization>
|
||||
<organizationUrl>http://www.neotechnology.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Lead</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>ogierke</id>
|
||||
<name>Oliver Gierke</name>
|
||||
<email>ogierke at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>http://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>trisberg</id>
|
||||
<name>Thomas Risberg</name>
|
||||
<email>trisberg at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>http://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mpollack</id>
|
||||
<name>Mark Pollack</name>
|
||||
<email>mpollack at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>http://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>vbickers</id>
|
||||
<name>Vince Bickers</name>
|
||||
<email>vince at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>GMT</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>atg</id>
|
||||
<name>Adam George</name>
|
||||
<email>adam at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>GMT</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>bachmanm</id>
|
||||
<name>Michal Bachman</name>
|
||||
<email>michal at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>GMT</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>lmisquitta</id>
|
||||
<name>Luanne Misquitta</name>
|
||||
<email>luanne at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+5:30</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mangrish</id>
|
||||
<name>Mark Angrish</name>
|
||||
<email>mark at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+11</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>jasperblues</id>
|
||||
<name>Jasper Blues</name>
|
||||
<email>jasper at graphaware.com</email>
|
||||
<organization>GraphAware</organization>
|
||||
<organizationUrl>http://www.graphaware.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+8</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mhunger</id>
|
||||
<name>Michael Hunger</name>
|
||||
<email>michael.hunger at neotechnology.com</email>
|
||||
<organization>Neo Technology</organization>
|
||||
<organizationUrl>http://www.neotechnology.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Lead</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>ogierke</id>
|
||||
<name>Oliver Gierke</name>
|
||||
<email>ogierke at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>http://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>trisberg</id>
|
||||
<name>Thomas Risberg</name>
|
||||
<email>trisberg at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>http://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mpollack</id>
|
||||
<name>Mark Pollack</name>
|
||||
<email>mpollack at gopivotal.com</email>
|
||||
<organization>Pivotal</organization>
|
||||
<organizationUrl>http://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>5.1.2.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>5.1.2.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencies>
|
||||
|
||||
</dependencyManagement>
|
||||
</dependencyManagement>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jfrog.buildinfo</groupId>
|
||||
<artifactId>artifactory-maven-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jfrog.buildinfo</groupId>
|
||||
<artifactId>artifactory-maven-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>neo4j</id>
|
||||
<url>http://m2.neo4j.org/content/repositories/releases</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>always</updatePolicy>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>neo4j-snapshots</id>
|
||||
<url>http://m2.neo4j.org/content/repositories/snapshots</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>always</updatePolicy>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-libs-snapshot</id>
|
||||
<url>https://repo.spring.io/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>neo4j</id>
|
||||
<url>http://m2.neo4j.org/content/repositories/releases</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>always</updatePolicy>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>neo4j-snapshots</id>
|
||||
<url>http://m2.neo4j.org/content/repositories/snapshots</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>always</updatePolicy>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-libs-snapshot</id>
|
||||
<url>https://repo.spring.io/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-plugins-release</id>
|
||||
<url>https://repo.spring.io/plugins-release</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-plugins-release</id>
|
||||
<url>https://repo.spring.io/plugins-release</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -12,188 +12,189 @@
|
||||
~
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-data-neo4j</artifactId>
|
||||
<artifactId>spring-data-neo4j</artifactId>
|
||||
|
||||
<name>Spring Data Neo4J - Core</name>
|
||||
<description>Neo4J support for Spring Data</description>
|
||||
<name>Spring Data Neo4J - Core</name>
|
||||
<description>Neo4J support for Spring Data</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>4.2.14.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>4.2.14.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<neo4j.ogm.version>2.1.6</neo4j.ogm.version>
|
||||
<ogm.properties>ogm-http.properties</ogm.properties>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
</properties>
|
||||
<properties>
|
||||
<neo4j.ogm.version>2.1.6</neo4j.ogm.version>
|
||||
<ogm.properties>ogm-http.properties</ogm.properties>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${slf4j}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${slf4j}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Data -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
<version>${springdata.commons}</version>
|
||||
</dependency>
|
||||
<!-- Spring Data -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
<version>${springdata.commons}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- CDI -->
|
||||
<dependency>
|
||||
<groupId>javax.enterprise</groupId>
|
||||
<artifactId>cdi-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- CDI -->
|
||||
<dependency>
|
||||
<groupId>javax.enterprise</groupId>
|
||||
<artifactId>cdi-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.el</groupId>
|
||||
<artifactId>el-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.el</groupId>
|
||||
<artifactId>el-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans.test</groupId>
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans.test</groupId>
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- JSR 303 Validation -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${validation}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- JSR 303 Validation -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${validation}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>4.2.0.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Neo4j OGM -->
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-core</artifactId>
|
||||
<version>${neo4j.ogm.version}</version>
|
||||
</dependency>
|
||||
<!-- Neo4j OGM -->
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-core</artifactId>
|
||||
<version>${neo4j.ogm.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-http-driver</artifactId>
|
||||
<version>${neo4j.ogm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-http-driver</artifactId>
|
||||
<version>${neo4j.ogm.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-test</artifactId>
|
||||
<version>${neo4j.ogm.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-security-enterprise</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-test</artifactId>
|
||||
<version>${neo4j.ogm.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-security-enterprise</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.19.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>integration-test</id>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<forkMode>once</forkMode>
|
||||
<systemPropertyVariables>
|
||||
<ogm.properties>${ogm.properties}</ogm.properties>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.19.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>integration-test</id>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<forkMode>once</forkMode>
|
||||
<systemPropertyVariables>
|
||||
<ogm.properties>${ogm.properties}</ogm.properties>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -23,10 +23,11 @@ import org.springframework.data.annotation.QueryAnnotation;
|
||||
|
||||
/**
|
||||
* Specifies the depth of the query. Used with derived finders.
|
||||
*
|
||||
* @author Luanne Misquitta
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Target({ ElementType.PARAMETER, ElementType.METHOD })
|
||||
@QueryAnnotation
|
||||
@Documented
|
||||
public @interface Depth {
|
||||
|
||||
@@ -13,9 +13,13 @@
|
||||
|
||||
package org.springframework.data.neo4j.annotation;
|
||||
|
||||
import org.springframework.data.annotation.QueryAnnotation;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import org.springframework.data.annotation.QueryAnnotation;
|
||||
|
||||
/**
|
||||
* Annotation to declare finder queries directly on repository methods.
|
||||
@@ -29,16 +33,16 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
public @interface Query {
|
||||
|
||||
static final String CLASS = "org.springframework.data.neo4j.annotation.Query";
|
||||
static final String VALUE = "value";
|
||||
static final String CLASS = "org.springframework.data.neo4j.annotation.Query";
|
||||
static final String VALUE = "value";
|
||||
|
||||
/**
|
||||
* Defines the Cypher query to be executed when the annotated method is called.
|
||||
*/
|
||||
String value() default "";
|
||||
/**
|
||||
* Defines the Cypher query to be executed when the annotated method is called.
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* @return simpler count-query to be executed for @{see Pageable}-support
|
||||
*/
|
||||
String countQuery() default "";
|
||||
/**
|
||||
* @return simpler count-query to be executed for @{see Pageable}-support
|
||||
*/
|
||||
String countQuery() default "";
|
||||
}
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
|
||||
package org.springframework.data.neo4j.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to be applied to interfaces and classes onto which arbitrary Cypher query results are to be mapped.
|
||||
@@ -25,6 +29,6 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
public @interface QueryResult {
|
||||
|
||||
// no annotation properties needed
|
||||
// no annotation properties needed
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package org.springframework.data.neo4j.conversion;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
|
||||
import org.neo4j.ogm.MetaData;
|
||||
import org.neo4j.ogm.metadata.ClassInfo;
|
||||
import org.neo4j.ogm.metadata.FieldInfo;
|
||||
@@ -22,14 +24,12 @@ import org.neo4j.ogm.typeconversion.ConversionCallback;
|
||||
import org.neo4j.ogm.typeconversion.ProxyAttributeConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
|
||||
/**
|
||||
* Specialisation of {@link GenericConversionService} that creates Spring-compatible converters from those known by the mapping
|
||||
* {@link MetaData}, allowing the OGM type converters to be reused throughout a Spring application.
|
||||
* Specialisation of {@link GenericConversionService} that creates Spring-compatible converters from those known by the
|
||||
* mapping {@link MetaData}, allowing the OGM type converters to be reused throughout a Spring application.
|
||||
*
|
||||
* @author Adam George
|
||||
* @author Luanne Misquitta
|
||||
@@ -37,86 +37,83 @@ import java.lang.reflect.ParameterizedType;
|
||||
*/
|
||||
public class MetaDataDrivenConversionService extends GenericConversionService implements ConversionCallback {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MetaDataDrivenConversionService.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(MetaDataDrivenConversionService.class);
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MetaDataDrivenConversionService} based on the given {@link MetaData}.
|
||||
*
|
||||
* @param metaData The OGM {@link MetaData} from which to elicit type converters configured in the underlying object-graph
|
||||
* mapping layer
|
||||
*/
|
||||
public MetaDataDrivenConversionService(MetaData metaData) {
|
||||
metaData.registerConversionCallback(this);
|
||||
/**
|
||||
* Constructs a new {@link MetaDataDrivenConversionService} based on the given {@link MetaData}.
|
||||
*
|
||||
* @param metaData The OGM {@link MetaData} from which to elicit type converters configured in the underlying
|
||||
* object-graph mapping layer
|
||||
*/
|
||||
public MetaDataDrivenConversionService(MetaData metaData) {
|
||||
metaData.registerConversionCallback(this);
|
||||
|
||||
for (ClassInfo classInfo : metaData.persistentEntities()) {
|
||||
for (FieldInfo fieldInfo : classInfo.propertyFields()) {
|
||||
if (fieldInfo.hasPropertyConverter()) {
|
||||
addWrappedConverter(fieldInfo.getPropertyConverter());
|
||||
}
|
||||
}
|
||||
// TODO: do we need to check the setters too or are programmers obliged to annotate both?
|
||||
for (MethodInfo methodInfo : classInfo.propertyGetters()) {
|
||||
if (methodInfo.hasPropertyConverter()) {
|
||||
addWrappedConverter(methodInfo.getPropertyConverter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ClassInfo classInfo : metaData.persistentEntities()) {
|
||||
for (FieldInfo fieldInfo : classInfo.propertyFields()) {
|
||||
if (fieldInfo.hasPropertyConverter()) {
|
||||
addWrappedConverter(fieldInfo.getPropertyConverter());
|
||||
}
|
||||
}
|
||||
// TODO: do we need to check the setters too or are programmers obliged to annotate both?
|
||||
for (MethodInfo methodInfo : classInfo.propertyGetters()) {
|
||||
if (methodInfo.hasPropertyConverter()) {
|
||||
addWrappedConverter(methodInfo.getPropertyConverter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private void addWrappedConverter(final AttributeConverter attributeConverter) {
|
||||
if (attributeConverter instanceof ProxyAttributeConverter) {
|
||||
return;
|
||||
}
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private void addWrappedConverter(final AttributeConverter attributeConverter) {
|
||||
if (attributeConverter instanceof ProxyAttributeConverter) {
|
||||
return;
|
||||
}
|
||||
|
||||
Converter toGraphConverter = new Converter() {
|
||||
@Override
|
||||
public Object convert(Object source) {
|
||||
return attributeConverter.toGraphProperty(source);
|
||||
}
|
||||
};
|
||||
Converter toEntityConverter = new Converter() {
|
||||
@Override
|
||||
public Object convert(Object source) {
|
||||
return attributeConverter.toEntityAttribute(source);
|
||||
}
|
||||
};
|
||||
Converter toGraphConverter = new Converter() {
|
||||
@Override
|
||||
public Object convert(Object source) {
|
||||
return attributeConverter.toGraphProperty(source);
|
||||
}
|
||||
};
|
||||
Converter toEntityConverter = new Converter() {
|
||||
@Override
|
||||
public Object convert(Object source) {
|
||||
return attributeConverter.toEntityAttribute(source);
|
||||
}
|
||||
};
|
||||
|
||||
ParameterizedType pt = (ParameterizedType) attributeConverter.getClass().getGenericInterfaces()[0];
|
||||
Class<?> sourceType, targetType;
|
||||
if (pt.getActualTypeArguments()[0] instanceof Class) {
|
||||
sourceType = (Class<?>) pt.getActualTypeArguments()[0];
|
||||
} else { // the argument may be a Collection for example
|
||||
sourceType = (Class<?>) ((ParameterizedType) pt.getActualTypeArguments()[0]).getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
ParameterizedType pt = (ParameterizedType) attributeConverter.getClass().getGenericInterfaces()[0];
|
||||
Class<?> sourceType, targetType;
|
||||
if (pt.getActualTypeArguments()[0] instanceof Class) {
|
||||
sourceType = (Class<?>) pt.getActualTypeArguments()[0];
|
||||
}
|
||||
else { //the argument may be a Collection for example
|
||||
sourceType = (Class<?>)((ParameterizedType) pt.getActualTypeArguments()[0]).getActualTypeArguments()[0];
|
||||
}
|
||||
if (pt.getActualTypeArguments()[1] instanceof Class) {
|
||||
targetType = (Class<?>) pt.getActualTypeArguments()[1];
|
||||
} else {
|
||||
targetType = (Class<?>) ((ParameterizedType) pt.getActualTypeArguments()[1]).getActualTypeArguments()[1];
|
||||
|
||||
if (pt.getActualTypeArguments()[1] instanceof Class) {
|
||||
targetType = (Class<?>) pt.getActualTypeArguments()[1];
|
||||
}
|
||||
else {
|
||||
targetType = (Class<?>)((ParameterizedType) pt.getActualTypeArguments()[1]).getActualTypeArguments()[1];
|
||||
}
|
||||
|
||||
}
|
||||
if (canConvert(sourceType, targetType) && canConvert(targetType, sourceType)) {
|
||||
logger.info("Not adding Spring-compatible converter for " + attributeConverter.getClass()
|
||||
+ " because one that does the same job has already been registered with the ConversionService.");
|
||||
} else {
|
||||
// It could be argued that this is wrong as it potentially overrides a registered converted that doesn't handle
|
||||
// both directions, but I've decided that it's better to ensure the same converter is used for load and save.
|
||||
addConverter(sourceType, targetType, toGraphConverter);
|
||||
addConverter(targetType, sourceType, toEntityConverter);
|
||||
}
|
||||
}
|
||||
|
||||
if (canConvert(sourceType, targetType) && canConvert(targetType, sourceType)) {
|
||||
logger.info("Not adding Spring-compatible converter for " + attributeConverter.getClass()
|
||||
+ " because one that does the same job has already been registered with the ConversionService.");
|
||||
} else {
|
||||
// It could be argued that this is wrong as it potentially overrides a registered converted that doesn't handle
|
||||
// both directions, but I've decided that it's better to ensure the same converter is used for load and save.
|
||||
addConverter(sourceType, targetType, toGraphConverter);
|
||||
addConverter(targetType, sourceType, toEntityConverter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T convert(Class<T> targetType, Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return convert(value, targetType);
|
||||
}
|
||||
@Override
|
||||
public <T> T convert(Class<T> targetType, Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return convert(value, targetType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,15 +11,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.data.neo4j.conversion;
|
||||
|
||||
import org.neo4j.ogm.typeconversion.CompositeAttributeConverter;
|
||||
import org.springframework.data.geo.Point;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.neo4j.ogm.typeconversion.CompositeAttributeConverter;
|
||||
import org.springframework.data.geo.Point;
|
||||
|
||||
/**
|
||||
* Converts latitude and longitude properties on a node entity to an instance of Point and vice-versa.
|
||||
*
|
||||
@@ -28,24 +27,24 @@ import java.util.Map;
|
||||
*/
|
||||
public class PointConverter implements CompositeAttributeConverter<Point> {
|
||||
|
||||
@Override
|
||||
public Map<String, ?> toGraphProperties(Point point) {
|
||||
Map<String, Double> properties = new HashMap<>();
|
||||
if (point != null) {
|
||||
properties.put("latitude", point.getX());
|
||||
properties.put("longitude", point.getY());
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
@Override
|
||||
public Map<String, ?> toGraphProperties(Point point) {
|
||||
Map<String, Double> properties = new HashMap<>();
|
||||
if (point != null) {
|
||||
properties.put("latitude", point.getX());
|
||||
properties.put("longitude", point.getY());
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point toEntityAttribute(Map<String, ?> map) {
|
||||
Double latitude = (Double) map.get("latitude");
|
||||
Double longitude = (Double) map.get("longitude");
|
||||
if (latitude != null && longitude != null) {
|
||||
return new Point(latitude, longitude);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Point toEntityAttribute(Map<String, ?> map) {
|
||||
Double latitude = (Double) map.get("latitude");
|
||||
Double longitude = (Double) map.get("longitude");
|
||||
if (latitude != null && longitude != null) {
|
||||
return new Point(latitude, longitude);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,14 +60,18 @@ public class Neo4jErrorStatusCodes {
|
||||
errors.put("Neo.ClientError.Statement.SemanticError", NonTransientDataAccessException.class);
|
||||
errors.put("Neo.ClientError.Statement.SyntaxError", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Statement.TypeError", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.ForbiddenDueToTransactionType", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionAccessedConcurrently", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionEventHandlerFailed", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.ForbiddenDueToTransactionType",
|
||||
InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionAccessedConcurrently",
|
||||
InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionEventHandlerFailed",
|
||||
InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionHookFailed", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionMarkedAsFailed", ConcurrencyFailureException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionNotFound", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionTerminated", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionValidationFailed", InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.ClientError.Transaction.TransactionValidationFailed",
|
||||
InvalidDataAccessResourceUsageException.class);
|
||||
errors.put("Neo.DatabaseError.General.IndexCorruptionDetected", DataAccessResourceFailureException.class);
|
||||
errors.put("Neo.DatabaseError.General.SchemaCorruptionDetected", DataAccessResourceFailureException.class);
|
||||
errors.put("Neo.DatabaseError.General.UnknownError", UncategorizedDataAccessException.class);
|
||||
|
||||
@@ -12,8 +12,13 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.mapping;
|
||||
|
||||
import org.neo4j.ogm.annotation.typeconversion.Convert;
|
||||
import static java.util.Collections.*;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.neo4j.ogm.MetaData;
|
||||
import org.neo4j.ogm.annotation.typeconversion.Convert;
|
||||
import org.neo4j.ogm.classloader.MetaDataClassLoader;
|
||||
import org.neo4j.ogm.metadata.ClassInfo;
|
||||
import org.neo4j.ogm.metadata.FieldInfo;
|
||||
@@ -23,17 +28,10 @@ import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
/**
|
||||
* This class implements Spring Data's MappingContext interface, scavenging the required data from the OGM's metadata in order
|
||||
* to for SDN to play nicely with Spring Data REST.
|
||||
*
|
||||
* The main thing to note is that this class is effectively a container shim for {@code ClassInfo} objects. We don't reload all
|
||||
* the mapping information again.
|
||||
* This class implements Spring Data's MappingContext interface, scavenging the required data from the OGM's metadata in
|
||||
* order to for SDN to play nicely with Spring Data REST. The main thing to note is that this class is effectively a
|
||||
* container shim for {@code ClassInfo} objects. We don't reload all the mapping information again.
|
||||
*
|
||||
* @author Vince Bickers
|
||||
* @author Adam George
|
||||
@@ -41,88 +39,90 @@ import static java.util.Collections.singleton;
|
||||
*/
|
||||
public class Neo4jMappingContext extends AbstractMappingContext<Neo4jPersistentEntity<?>, Neo4jPersistentProperty> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Neo4jMappingContext.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(Neo4jMappingContext.class);
|
||||
|
||||
private final MetaData metaData;
|
||||
private final MetaData metaData;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Neo4jMappingContext} based on the persistent entities in the given {@link MetaData}.
|
||||
*
|
||||
* @param metaData The OGM {@link MetaData} from which to extract the persistent entities
|
||||
*/
|
||||
public Neo4jMappingContext(MetaData metaData) {
|
||||
this.metaData = metaData;
|
||||
/**
|
||||
* Constructs a new {@link Neo4jMappingContext} based on the persistent entities in the given {@link MetaData}.
|
||||
*
|
||||
* @param metaData The OGM {@link MetaData} from which to extract the persistent entities
|
||||
*/
|
||||
public Neo4jMappingContext(MetaData metaData) {
|
||||
this.metaData = metaData;
|
||||
|
||||
for (ClassInfo classInfo : metaData.persistentEntities()) {
|
||||
try {
|
||||
addPersistentEntity( MetaDataClassLoader.loadClass( classInfo.name() ));
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error("Failed to load class: " + classInfo.name() + " named in ClassInfo due to exception", e);
|
||||
}
|
||||
}
|
||||
for (ClassInfo classInfo : metaData.persistentEntities()) {
|
||||
try {
|
||||
addPersistentEntity(MetaDataClassLoader.loadClass(classInfo.name()));
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error("Failed to load class: " + classInfo.name() + " named in ClassInfo due to exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Neo4jMappingContext initialisation completed");
|
||||
}
|
||||
logger.info("Neo4jMappingContext initialisation completed");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> Neo4jPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
logger.debug("Creating Neo4jPersistentEntity from type information: {}", typeInformation);
|
||||
return new Neo4jPersistentEntity<>(typeInformation);
|
||||
}
|
||||
@Override
|
||||
protected <T> Neo4jPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
logger.debug("Creating Neo4jPersistentEntity from type information: {}", typeInformation);
|
||||
return new Neo4jPersistentEntity<>(typeInformation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Neo4jPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, Neo4jPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
@Override
|
||||
protected Neo4jPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
Neo4jPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
ClassInfo owningClassInfo = this.metaData.classInfo(owner.getType().getName());
|
||||
ClassInfo owningClassInfo = this.metaData.classInfo(owner.getType().getName());
|
||||
|
||||
Field propertyField = field;
|
||||
if (propertyField == null && owningClassInfo != null && descriptor != null) {
|
||||
FieldInfo fieldInfo = owningClassInfo.propertyFieldByName(descriptor.getName());
|
||||
if (fieldInfo == null) {
|
||||
fieldInfo = owningClassInfo.relationshipFieldByName(descriptor.getName());
|
||||
}
|
||||
if (fieldInfo != null) {
|
||||
propertyField = owningClassInfo.getField(fieldInfo);
|
||||
} else {
|
||||
// there is no field, probably because descriptor gave us a field name derived from a getter
|
||||
logger.debug("Couldn't resolve a concrete field corresponding to property {} on {} ",
|
||||
descriptor.getName(), owningClassInfo.name());
|
||||
}
|
||||
}
|
||||
Field propertyField = field;
|
||||
if (propertyField == null && owningClassInfo != null && descriptor != null) {
|
||||
FieldInfo fieldInfo = owningClassInfo.propertyFieldByName(descriptor.getName());
|
||||
if (fieldInfo == null) {
|
||||
fieldInfo = owningClassInfo.relationshipFieldByName(descriptor.getName());
|
||||
}
|
||||
if (fieldInfo != null) {
|
||||
propertyField = owningClassInfo.getField(fieldInfo);
|
||||
} else {
|
||||
// there is no field, probably because descriptor gave us a field name derived from a getter
|
||||
logger.debug("Couldn't resolve a concrete field corresponding to property {} on {} ", descriptor.getName(),
|
||||
owningClassInfo.name());
|
||||
}
|
||||
}
|
||||
|
||||
return new Neo4jPersistentProperty(owningClassInfo, propertyField, descriptor, owner,
|
||||
updateSimpleTypeHolder(simpleTypeHolder, propertyField));
|
||||
}
|
||||
return new Neo4jPersistentProperty(owningClassInfo, propertyField, descriptor, owner,
|
||||
updateSimpleTypeHolder(simpleTypeHolder, propertyField));
|
||||
}
|
||||
|
||||
private SimpleTypeHolder updateSimpleTypeHolder(SimpleTypeHolder currentSimpleTypeHolder, Field field) {
|
||||
if (field == null) {
|
||||
return currentSimpleTypeHolder;
|
||||
}
|
||||
private SimpleTypeHolder updateSimpleTypeHolder(SimpleTypeHolder currentSimpleTypeHolder, Field field) {
|
||||
if (field == null) {
|
||||
return currentSimpleTypeHolder;
|
||||
}
|
||||
|
||||
final Class<?> fieldType = field.getType().isArray() ? field.getType().getComponentType() : field.getType();
|
||||
final Class<?> fieldType = field.getType().isArray() ? field.getType().getComponentType() : field.getType();
|
||||
|
||||
if (shouldUpdateSimpleTypes(currentSimpleTypeHolder, field, fieldType)) {
|
||||
SimpleTypeHolder updatedSimpleTypeHolder = new SimpleTypeHolder(singleton(fieldType), currentSimpleTypeHolder);
|
||||
setSimpleTypeHolder(updatedSimpleTypeHolder);
|
||||
return updatedSimpleTypeHolder;
|
||||
}
|
||||
return currentSimpleTypeHolder;
|
||||
}
|
||||
if (shouldUpdateSimpleTypes(currentSimpleTypeHolder, field, fieldType)) {
|
||||
SimpleTypeHolder updatedSimpleTypeHolder = new SimpleTypeHolder(singleton(fieldType), currentSimpleTypeHolder);
|
||||
setSimpleTypeHolder(updatedSimpleTypeHolder);
|
||||
return updatedSimpleTypeHolder;
|
||||
}
|
||||
return currentSimpleTypeHolder;
|
||||
}
|
||||
|
||||
private boolean shouldUpdateSimpleTypes(SimpleTypeHolder currentSimpleTypeHolder, Field field, Class<?> rawFieldType) {
|
||||
if (field.isAnnotationPresent(Convert.class)) {
|
||||
return true;
|
||||
}
|
||||
private boolean shouldUpdateSimpleTypes(SimpleTypeHolder currentSimpleTypeHolder, Field field,
|
||||
Class<?> rawFieldType) {
|
||||
if (field.isAnnotationPresent(Convert.class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentSimpleTypeHolder.isSimpleType(rawFieldType) || rawFieldType.isInterface()) {
|
||||
return false;
|
||||
}
|
||||
if (this.metaData.classInfo(rawFieldType.getName()) == null) {
|
||||
logger.info("No class information found in OGM meta-data for {} so treating as simple type for SD Commons", rawFieldType);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (currentSimpleTypeHolder.isSimpleType(rawFieldType) || rawFieldType.isInterface()) {
|
||||
return false;
|
||||
}
|
||||
if (this.metaData.classInfo(rawFieldType.getName()) == null) {
|
||||
logger.info("No class information found in OGM meta-data for {} so treating as simple type for SD Commons",
|
||||
rawFieldType);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,22 +19,20 @@ import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* This class implements Spring Data's PersistentEntity interface, scavenging the required data from the OGM's mapping classes
|
||||
* in order to for SDN to play nicely with Spring Data REST.
|
||||
*
|
||||
* The main thing to note is that this class is effectively a shim for ClassInfo. We don't reload all the mapping information
|
||||
* again.
|
||||
* This class implements Spring Data's PersistentEntity interface, scavenging the required data from the OGM's mapping
|
||||
* classes in order to for SDN to play nicely with Spring Data REST. The main thing to note is that this class is
|
||||
* effectively a shim for ClassInfo. We don't reload all the mapping information again.
|
||||
* <p>
|
||||
* These attributes do not appear to be used/needed for SDN 4 to inter-operate correctly with SD-REST:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>typeAlias</li>
|
||||
* <li>typeInformation</li>
|
||||
* <li>preferredConstructor (we always use the default constructor)</li>
|
||||
* <li>versionProperty</li>
|
||||
* <li>typeAlias</li>
|
||||
* <li>typeInformation</li>
|
||||
* <li>preferredConstructor (we always use the default constructor)</li>
|
||||
* <li>versionProperty</li>
|
||||
* </ul>
|
||||
* Consequently their associated getter methods always return default values of null or [true|false] However, because these
|
||||
* method calls are not expected, we also log a warning message if they get invoked
|
||||
* Consequently their associated getter methods always return default values of null or [true|false] However, because
|
||||
* these method calls are not expected, we also log a warning message if they get invoked
|
||||
*
|
||||
* @author Vince Bickers
|
||||
* @author Adam George
|
||||
@@ -42,33 +40,33 @@ import org.springframework.data.util.TypeInformation;
|
||||
*/
|
||||
public class Neo4jPersistentEntity<T> extends BasicPersistentEntity<T, Neo4jPersistentProperty> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Neo4jPersistentEntity.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(Neo4jPersistentEntity.class);
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Neo4jPersistentEntity} based on the given type information.
|
||||
*
|
||||
* @param information The {@link TypeInformation} upon which to base this persistent entity.
|
||||
*/
|
||||
public Neo4jPersistentEntity(TypeInformation<T> information) {
|
||||
super(information);
|
||||
}
|
||||
/**
|
||||
* Constructs a new {@link Neo4jPersistentEntity} based on the given type information.
|
||||
*
|
||||
* @param information The {@link TypeInformation} upon which to base this persistent entity.
|
||||
*/
|
||||
public Neo4jPersistentEntity(TypeInformation<T> information) {
|
||||
super(information);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVersionProperty() {
|
||||
logger.debug("[entity].hasVersionProperty() returns false"); // by design
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean hasVersionProperty() {
|
||||
logger.debug("[entity].hasVersionProperty() returns false"); // by design
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Neo4jPersistentProperty getVersionProperty() {
|
||||
logger.debug("[entity].getVersionProperty() returns null"); // by design
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Neo4jPersistentProperty getVersionProperty() {
|
||||
logger.debug("[entity].getVersionProperty() returns null"); // by design
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionProperty(PersistentProperty<?> property) {
|
||||
logger.debug("[entity].isIdProperty({}) returns false", property); // again, by design
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isVersionProperty(PersistentProperty<?> property) {
|
||||
logger.debug("[entity].isIdProperty({}) returns false", property); // again, by design
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,11 +29,10 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.neo4j.annotation.QueryResult;
|
||||
|
||||
/**
|
||||
* This class implements Spring Data's PersistentProperty interface, scavenging the required data from the
|
||||
* OGM's mapping classes in order to for SDN to play nicely with Spring Data REST.
|
||||
* The main thing to note is that this class is effectively a shim for FieldInfo. We don't reload
|
||||
* all the mapping information again.
|
||||
* We do not yet support getter/setter access to entity properties.
|
||||
* This class implements Spring Data's PersistentProperty interface, scavenging the required data from the OGM's mapping
|
||||
* classes in order to for SDN to play nicely with Spring Data REST. The main thing to note is that this class is
|
||||
* effectively a shim for FieldInfo. We don't reload all the mapping information again. We do not yet support
|
||||
* getter/setter access to entity properties.
|
||||
* <p>
|
||||
* These attributes do not appear to be used/needed for SDN 4 to inter-operate correctly with SD-REST:
|
||||
* </p>
|
||||
@@ -44,8 +43,8 @@ import org.springframework.data.neo4j.annotation.QueryResult;
|
||||
* <li>isTransient (we never supply transient classes to the Spring mapping context)</li>
|
||||
* <li>isWritable (we don't currently support read-only fields)</li>
|
||||
* </ul>
|
||||
* Consequently their associated getter methods always return default values of null or [true|false]
|
||||
* However, because these method calls are not expected, we also log a warning message if they get invoked
|
||||
* Consequently their associated getter methods always return default values of null or [true|false] However, because
|
||||
* these method calls are not expected, we also log a warning message if they get invoked
|
||||
*
|
||||
* @author Vince Bickers
|
||||
* @author Adam George
|
||||
@@ -66,17 +65,22 @@ public class Neo4jPersistentProperty extends AnnotationBasedPersistentProperty<N
|
||||
* @param field The property {@link Field}
|
||||
* @param descriptor The Java bean {@link PropertyDescriptor}
|
||||
* @param owner The owning {@link PersistentEntity} that corresponds to the given {@code ClassInfo}
|
||||
* @param simpleTypeHolder The {@link SimpleTypeHolder} that dictates whether the type of this property is considered simple
|
||||
* or not
|
||||
* @param simpleTypeHolder The {@link SimpleTypeHolder} that dictates whether the type of this property is considered
|
||||
* simple or not
|
||||
*/
|
||||
public Neo4jPersistentProperty(ClassInfo owningClassInfo, Field field, PropertyDescriptor descriptor,
|
||||
PersistentEntity<?, Neo4jPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
PersistentEntity<?, Neo4jPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
super(field, descriptor, owner, simpleTypeHolder);
|
||||
if (owningClassInfo == null) {
|
||||
logger.warn("Owning ClassInfo is null for field: {} and propertyDescriptor: {}", field, descriptor);
|
||||
}
|
||||
if ((owningClassInfo != null && owningClassInfo.getUnderlyingClass() != null && simpleTypeHolder.isSimpleType(owningClassInfo.getUnderlyingClass()))
|
||||
|| owner.getType().isEnum()) { //TODO refactor all these null checks
|
||||
if ((owningClassInfo != null && owningClassInfo.getUnderlyingClass() != null
|
||||
&& simpleTypeHolder.isSimpleType(owningClassInfo.getUnderlyingClass())) || owner.getType().isEnum()) { // TODO
|
||||
// refactor
|
||||
// all
|
||||
// these
|
||||
// null
|
||||
// checks
|
||||
this.isIdProperty = false;
|
||||
} else {
|
||||
this.isIdProperty = resolveWhetherIdProperty(owningClassInfo, field);
|
||||
@@ -84,7 +88,8 @@ public class Neo4jPersistentProperty extends AnnotationBasedPersistentProperty<N
|
||||
}
|
||||
|
||||
private static boolean resolveWhetherIdProperty(ClassInfo owningClassInfo, Field field) {
|
||||
if (owningClassInfo == null || owningClassInfo.isInterface() || owningClassInfo.annotationsInfo().get(QueryResult.class.getName()) != null || owningClassInfo.isEnum()) {
|
||||
if (owningClassInfo == null || owningClassInfo.isInterface()
|
||||
|| owningClassInfo.annotationsInfo().get(QueryResult.class.getName()) != null || owningClassInfo.isEnum()) {
|
||||
// no ID properties on @QueryResult or non-concrete objects
|
||||
return false;
|
||||
} else {
|
||||
@@ -122,8 +127,8 @@ public class Neo4jPersistentProperty extends AnnotationBasedPersistentProperty<N
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not this property should be considered an association to another entity or whether it's
|
||||
* just a simple property that should be shown as a value.
|
||||
* Determines whether or not this property should be considered an association to another entity or whether it's just
|
||||
* a simple property that should be shown as a value.
|
||||
* <p>
|
||||
* This implementation works by looking for non-transient members annotated with <code>@Relationship</code>.
|
||||
* </p>
|
||||
@@ -132,10 +137,8 @@ public class Neo4jPersistentProperty extends AnnotationBasedPersistentProperty<N
|
||||
*/
|
||||
@Override
|
||||
public boolean isAssociation() {
|
||||
return !isTransient() &&
|
||||
(isAnnotationPresent(Relationship.class)
|
||||
|| isAnnotationPresent(StartNode.class)
|
||||
|| isAnnotationPresent(EndNode.class));
|
||||
return !isTransient() && (isAnnotationPresent(Relationship.class) || isAnnotationPresent(StartNode.class)
|
||||
|| isAnnotationPresent(EndNode.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository;
|
||||
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -40,7 +39,6 @@ public interface GraphRepository<T> extends Neo4jRepository<T, Long> {
|
||||
|
||||
Iterable<T> findAll(Sort sort, int depth);
|
||||
|
||||
|
||||
Iterable<T> findAll(Iterable<Long> ids);
|
||||
|
||||
Iterable<T> findAll(Iterable<Long> ids, int depth);
|
||||
@@ -51,7 +49,8 @@ public interface GraphRepository<T> extends Neo4jRepository<T, Long> {
|
||||
|
||||
/**
|
||||
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
|
||||
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for accuracy.
|
||||
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for
|
||||
* accuracy.
|
||||
*
|
||||
* @param pageable
|
||||
* @return a page of entities
|
||||
@@ -60,7 +59,8 @@ public interface GraphRepository<T> extends Neo4jRepository<T, Long> {
|
||||
|
||||
/**
|
||||
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
|
||||
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for accuracy.
|
||||
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for
|
||||
* accuracy.
|
||||
*
|
||||
* @param pageable
|
||||
* @param depth
|
||||
|
||||
@@ -54,7 +54,8 @@ public interface Neo4jRepository<T, ID extends Serializable> extends PagingAndSo
|
||||
|
||||
/**
|
||||
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
|
||||
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for accuracy.
|
||||
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for
|
||||
* accuracy.
|
||||
*
|
||||
* @param pageable
|
||||
* @return a page of entities
|
||||
@@ -63,7 +64,8 @@ public interface Neo4jRepository<T, ID extends Serializable> extends PagingAndSo
|
||||
|
||||
/**
|
||||
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
|
||||
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for accuracy.
|
||||
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for
|
||||
* accuracy.
|
||||
*
|
||||
* @param pageable
|
||||
* @param depth
|
||||
|
||||
@@ -16,16 +16,17 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.cdi;
|
||||
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactory;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryBean;
|
||||
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactory;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryBean;
|
||||
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.data.repository.cdi.CdiRepositoryBean} to create Neo4j repository instances via CDI.
|
||||
@@ -34,30 +35,30 @@ import java.util.Set;
|
||||
* @since 4.2
|
||||
*/
|
||||
public class Neo4jCdiRepositoryBean<T> extends CdiRepositoryBean<T> {
|
||||
private final Bean<Session> sessionBean;
|
||||
private final Bean<Session> sessionBean;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Neo4jCdiRepositoryBean}.
|
||||
*
|
||||
* @param sessionBean must not be {@literal null}.
|
||||
* @param qualifiers must not be {@literal null}.
|
||||
* @param repositoryType must not be {@literal null}.
|
||||
* @param beanManager must not be {@literal null}.
|
||||
* @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations
|
||||
* {@link CustomRepositoryImplementationDetector}, can be {@literal null}.
|
||||
*/
|
||||
public Neo4jCdiRepositoryBean(Bean<Session> sessionBean, Set<Annotation> qualifiers, Class<T> repositoryType,
|
||||
BeanManager beanManager, CustomRepositoryImplementationDetector detector) {
|
||||
super(qualifiers, repositoryType, beanManager, detector);
|
||||
this.sessionBean = sessionBean;
|
||||
}
|
||||
/**
|
||||
* Creates a new {@link Neo4jCdiRepositoryBean}.
|
||||
*
|
||||
* @param sessionBean must not be {@literal null}.
|
||||
* @param qualifiers must not be {@literal null}.
|
||||
* @param repositoryType must not be {@literal null}.
|
||||
* @param beanManager must not be {@literal null}.
|
||||
* @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations
|
||||
* {@link CustomRepositoryImplementationDetector}, can be {@literal null}.
|
||||
*/
|
||||
public Neo4jCdiRepositoryBean(Bean<Session> sessionBean, Set<Annotation> qualifiers, Class<T> repositoryType,
|
||||
BeanManager beanManager, CustomRepositoryImplementationDetector detector) {
|
||||
super(qualifiers, repositoryType, beanManager, detector);
|
||||
this.sessionBean = sessionBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Object customImplementation) {
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Object customImplementation) {
|
||||
|
||||
Session session = getDependencyInstance(sessionBean, Session.class);
|
||||
Session session = getDependencyInstance(sessionBean, Session.class);
|
||||
|
||||
Neo4jRepositoryFactory factory = new Neo4jRepositoryFactory(session);
|
||||
return factory.getRepository(repositoryType, customImplementation);
|
||||
}
|
||||
Neo4jRepositoryFactory factory = new Neo4jRepositoryFactory(session);
|
||||
return factory.getRepository(repositoryType, customImplementation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,18 +16,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.cdi;
|
||||
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryBean;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
|
||||
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.enterprise.inject.UnsatisfiedResolutionException;
|
||||
import javax.enterprise.inject.spi.AfterBeanDiscovery;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.enterprise.inject.spi.ProcessBean;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
@@ -36,6 +24,19 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.enterprise.inject.UnsatisfiedResolutionException;
|
||||
import javax.enterprise.inject.spi.AfterBeanDiscovery;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.enterprise.inject.spi.ProcessBean;
|
||||
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryBean;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
|
||||
|
||||
/**
|
||||
* CDI extension to export Neo4j repositories.
|
||||
*
|
||||
@@ -44,68 +45,66 @@ import java.util.Set;
|
||||
*/
|
||||
public class Neo4jCdiRepositoryExtension extends CdiRepositoryExtensionSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Neo4jCdiRepositoryExtension.class);
|
||||
private final Map<Set<Annotation>, Bean<Session>> sessions = new HashMap<Set<Annotation>, Bean<Session>>();
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Neo4jCdiRepositoryExtension.class);
|
||||
private final Map<Set<Annotation>, Bean<Session>> sessions = new HashMap<Set<Annotation>, Bean<Session>>();
|
||||
|
||||
public Neo4jCdiRepositoryExtension() {
|
||||
LOG.info("Activating CDI extension for Spring Data Neo4j repositories.");
|
||||
}
|
||||
public Neo4jCdiRepositoryExtension() {
|
||||
LOG.info("Activating CDI extension for Spring Data Neo4j repositories.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<X> void processBean(@Observes ProcessBean<X> processBean) {
|
||||
Bean<X> bean = processBean.getBean();
|
||||
@SuppressWarnings("unchecked")
|
||||
<X> void processBean(@Observes ProcessBean<X> processBean) {
|
||||
Bean<X> bean = processBean.getBean();
|
||||
|
||||
for (Type type : bean.getTypes()) {
|
||||
if (type instanceof Class<?> && Session.class.isAssignableFrom((Class<?>) type)) {
|
||||
for (Type type : bean.getTypes()) {
|
||||
if (type instanceof Class<?> && Session.class.isAssignableFrom((Class<?>) type)) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(String.format("Discovered %s with qualifiers %s.", Session.class.getName(),
|
||||
bean.getQualifiers()));
|
||||
}
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(String.format("Discovered %s with qualifiers %s.", Session.class.getName(), bean.getQualifiers()));
|
||||
}
|
||||
|
||||
sessions.put(new HashSet<Annotation>(bean.getQualifiers()), (Bean<Session>) bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
sessions.put(new HashSet<Annotation>(bean.getQualifiers()), (Bean<Session>) bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
|
||||
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
|
||||
|
||||
for (Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
|
||||
for (Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
|
||||
|
||||
Class<?> repositoryType = entry.getKey();
|
||||
Set<Annotation> qualifiers = entry.getValue();
|
||||
Class<?> repositoryType = entry.getKey();
|
||||
Set<Annotation> qualifiers = entry.getValue();
|
||||
|
||||
// Create the bean representing the repository.
|
||||
CdiRepositoryBean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info(String.format("Registering bean for %s with qualifiers %s.", repositoryType.getName(),
|
||||
qualifiers));
|
||||
}
|
||||
// Create the bean representing the repository.
|
||||
CdiRepositoryBean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info(String.format("Registering bean for %s with qualifiers %s.", repositoryType.getName(), qualifiers));
|
||||
}
|
||||
|
||||
// Register the bean to the container.
|
||||
registerBean(repositoryBean);
|
||||
afterBeanDiscovery.addBean(repositoryBean);
|
||||
}
|
||||
}
|
||||
// Register the bean to the container.
|
||||
registerBean(repositoryBean);
|
||||
afterBeanDiscovery.addBean(repositoryBean);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Bean}.
|
||||
*
|
||||
* @param <T> The type of the repository.
|
||||
* @param repositoryType The class representing the repository.
|
||||
* @param beanManager The BeanManager instance.
|
||||
* @return The bean.
|
||||
*/
|
||||
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
|
||||
BeanManager beanManager) {
|
||||
Bean<Session> sessionBean = this.sessions.get(qualifiers);
|
||||
/**
|
||||
* Creates a {@link Bean}.
|
||||
*
|
||||
* @param <T> The type of the repository.
|
||||
* @param repositoryType The class representing the repository.
|
||||
* @param beanManager The BeanManager instance.
|
||||
* @return The bean.
|
||||
*/
|
||||
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
|
||||
BeanManager beanManager) {
|
||||
Bean<Session> sessionBean = this.sessions.get(qualifiers);
|
||||
|
||||
if (sessionBean == null) {
|
||||
throw new UnsatisfiedResolutionException(String.format(
|
||||
"Unable to resolve a bean for '%s' with qualifiers %s.", Session.class.getName(), qualifiers));
|
||||
}
|
||||
if (sessionBean == null) {
|
||||
throw new UnsatisfiedResolutionException(
|
||||
String.format("Unable to resolve a bean for '%s' with qualifiers %s.", Session.class.getName(), qualifiers));
|
||||
}
|
||||
|
||||
return new Neo4jCdiRepositoryBean<T>(sessionBean, qualifiers, repositoryType, beanManager,
|
||||
getCustomImplementationDetector());
|
||||
}
|
||||
return new Neo4jCdiRepositoryBean<T>(sessionBean, qualifiers, repositoryType, beanManager,
|
||||
getCustomImplementationDetector());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,12 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.config;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
@@ -37,93 +42,93 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
@Import(Neo4jRepositoriesRegistrar.class)
|
||||
public @interface EnableNeo4jRepositories {
|
||||
|
||||
/**
|
||||
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
|
||||
* {@code @EnableExperimentalNeo4jRepositories("org.my.pkg")} instead of
|
||||
* {@code @EnableExperimentalNeo4jRepositories(basePackages="org.my.pkg")}.
|
||||
*/
|
||||
String[] value() default {};
|
||||
/**
|
||||
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
|
||||
* {@code @EnableExperimentalNeo4jRepositories("org.my.pkg")} instead of
|
||||
* {@code @EnableExperimentalNeo4jRepositories(basePackages="org.my.pkg")}.
|
||||
*/
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
|
||||
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
|
||||
*/
|
||||
String[] basePackages() default {};
|
||||
/**
|
||||
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
|
||||
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
|
||||
*/
|
||||
String[] basePackages() default {};
|
||||
|
||||
/**
|
||||
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The
|
||||
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
|
||||
* each package that serves no purpose other than being referenced by this attribute.
|
||||
*/
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
/**
|
||||
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The
|
||||
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
|
||||
* each package that serves no purpose other than being referenced by this attribute.
|
||||
*/
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
/**
|
||||
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
|
||||
* everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters.
|
||||
*/
|
||||
ComponentScan.Filter[] includeFilters() default {};
|
||||
/**
|
||||
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
|
||||
* everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters.
|
||||
*/
|
||||
ComponentScan.Filter[] includeFilters() default {};
|
||||
|
||||
/**
|
||||
* Specifies which types are not eligible for component scanning.
|
||||
*/
|
||||
ComponentScan.Filter[] excludeFilters() default {};
|
||||
/**
|
||||
* Specifies which types are not eligible for component scanning.
|
||||
*/
|
||||
ComponentScan.Filter[] excludeFilters() default {};
|
||||
|
||||
/**
|
||||
* Returns the postfix to be used when looking up custom repository implementations. Defaults to {@literal Impl}. So
|
||||
* for a repository named {@code PersonRepository} the corresponding implementation class will be looked up scanning
|
||||
* for {@code PersonRepositoryImpl}.
|
||||
*/
|
||||
String repositoryImplementationPostfix() default "Impl";
|
||||
/**
|
||||
* Returns the postfix to be used when looking up custom repository implementations. Defaults to {@literal Impl}. So
|
||||
* for a repository named {@code PersonRepository} the corresponding implementation class will be looked up scanning
|
||||
* for {@code PersonRepositoryImpl}.
|
||||
*/
|
||||
String repositoryImplementationPostfix() default "Impl";
|
||||
|
||||
/**
|
||||
* Configures the location of where to find the Spring Data named queries properties file. Will default to
|
||||
* {@code META-INFO/neo4j-named-queries.properties}.
|
||||
*/
|
||||
String namedQueriesLocation() default "";
|
||||
/**
|
||||
* Configures the location of where to find the Spring Data named queries properties file. Will default to
|
||||
* {@code META-INFO/neo4j-named-queries.properties}.
|
||||
*/
|
||||
String namedQueriesLocation() default "";
|
||||
|
||||
/**
|
||||
* Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to
|
||||
* {@link org.springframework.data.repository.query.QueryLookupStrategy.Key#CREATE_IF_NOT_FOUND}.
|
||||
*/
|
||||
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
|
||||
/**
|
||||
* Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to
|
||||
* {@link org.springframework.data.repository.query.QueryLookupStrategy.Key#CREATE_IF_NOT_FOUND}.
|
||||
*/
|
||||
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
|
||||
|
||||
/**
|
||||
* Returns the {@link org.springframework.beans.factory.FactoryBean} class to be used for each repository instance. Defaults to
|
||||
* {@link Neo4jRepositoryFactoryBean}.
|
||||
*/
|
||||
Class<?> repositoryFactoryBeanClass() default Neo4jRepositoryFactoryBean.class;
|
||||
/**
|
||||
* Returns the {@link org.springframework.beans.factory.FactoryBean} class to be used for each repository instance.
|
||||
* Defaults to {@link Neo4jRepositoryFactoryBean}.
|
||||
*/
|
||||
Class<?> repositoryFactoryBeanClass() default Neo4jRepositoryFactoryBean.class;
|
||||
|
||||
/**
|
||||
* Configure the repository base class to be used to create repository proxies for this particular configuration.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
|
||||
/**
|
||||
* Configure the repository base class to be used to create repository proxies for this particular configuration.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
|
||||
|
||||
/**
|
||||
* Configures the name of the {@link SessionFactory} bean definition to be used to create repositories
|
||||
* discovered through this annotation. Defaults to {@code sessionFactory}.
|
||||
*/
|
||||
String sessionFactoryRef() default "sessionFactory";
|
||||
/**
|
||||
* Configures the name of the {@link SessionFactory} bean definition to be used to create repositories discovered
|
||||
* through this annotation. Defaults to {@code sessionFactory}.
|
||||
*/
|
||||
String sessionFactoryRef() default "sessionFactory";
|
||||
|
||||
/**
|
||||
* Configures the name of the {@link PlatformTransactionManager} bean definition to be used to create repositories
|
||||
* discovered through this annotation. Defaults to {@code transactionManager}.
|
||||
*/
|
||||
String transactionManagerRef() default "transactionManager";
|
||||
/**
|
||||
* Configures the name of the {@link PlatformTransactionManager} bean definition to be used to create repositories
|
||||
* discovered through this annotation. Defaults to {@code transactionManager}.
|
||||
*/
|
||||
String transactionManagerRef() default "transactionManager";
|
||||
|
||||
/**
|
||||
* Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the
|
||||
* repositories infrastructure.
|
||||
*/
|
||||
boolean considerNestedRepositories() default false;
|
||||
/**
|
||||
* Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the
|
||||
* repositories infrastructure.
|
||||
*/
|
||||
boolean considerNestedRepositories() default false;
|
||||
|
||||
/**
|
||||
* Configures whether to enable default transactions for Spring Data Neo4j repositories. Defaults to {@literal true}. If
|
||||
* disabled, repositories must be used behind a facade that's configuring transactions (e.g. using Spring's annotation
|
||||
* driven transaction facilities) or repository methods have to be used to demarcate transactions.
|
||||
*
|
||||
* @return whether to enable default transactions, defaults to {@literal true}.
|
||||
*/
|
||||
boolean enableDefaultTransactions() default true;
|
||||
/**
|
||||
* Configures whether to enable default transactions for Spring Data Neo4j repositories. Defaults to {@literal true}.
|
||||
* If disabled, repositories must be used behind a facade that's configuring transactions (e.g. using Spring's
|
||||
* annotation driven transaction facilities) or repository methods have to be used to demarcate transactions.
|
||||
*
|
||||
* @return whether to enable default transactions, defaults to {@literal true}.
|
||||
*/
|
||||
boolean enableDefaultTransactions() default true;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.config;
|
||||
|
||||
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
@@ -28,8 +27,8 @@ import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
|
||||
*
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
class Neo4jMappingContextFactoryBean extends AbstractFactoryBean<Neo4jMappingContext> implements
|
||||
ApplicationContextAware {
|
||||
class Neo4jMappingContextFactoryBean extends AbstractFactoryBean<Neo4jMappingContext>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
@@ -52,9 +51,9 @@ class Neo4jMappingContextFactoryBean extends AbstractFactoryBean<Neo4jMappingCon
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
|
||||
*/
|
||||
@Override
|
||||
protected Neo4jMappingContext createInstance() throws Exception {
|
||||
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* @author Vince Bickers
|
||||
* @author Mark Angrish
|
||||
|
||||
@@ -83,7 +83,6 @@ public class Neo4jRepositoryConfigurationExtension extends RepositoryConfigurati
|
||||
return MODULE_PREFIX;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getIdentifyingAnnotations()
|
||||
@@ -175,7 +174,8 @@ public class Neo4jRepositoryConfigurationExtension extends RepositoryConfigurati
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(SharedSessionCreator.class,
|
||||
"createSharedSession");
|
||||
builder.addConstructorArgReference(sessionFactoryBeanName == null ? DEFAULT_SESSION_FACTORY_BEAN_NAME : sessionFactoryBeanName);
|
||||
builder.addConstructorArgReference(
|
||||
sessionFactoryBeanName == null ? DEFAULT_SESSION_FACTORY_BEAN_NAME : sessionFactoryBeanName);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.query;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
@@ -20,8 +22,6 @@ import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author Mark Angrish
|
||||
* @author Luanne Misquitta
|
||||
@@ -29,19 +29,19 @@ import java.lang.reflect.Method;
|
||||
*/
|
||||
public class GraphQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
private final Session session;
|
||||
private final Session session;
|
||||
|
||||
public GraphQueryLookupStrategy(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
|
||||
*/
|
||||
@Override
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
NamedQueries namedQueries) {
|
||||
return new GraphQueryMethod(method, metadata, factory, session).createQuery();
|
||||
}
|
||||
public GraphQueryLookupStrategy(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
|
||||
*/
|
||||
@Override
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
NamedQueries namedQueries) {
|
||||
return new GraphQueryMethod(method, metadata, factory, session).createQuery();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,131 +36,128 @@ import org.springframework.data.repository.query.RepositoryQuery;
|
||||
*/
|
||||
public class GraphQueryMethod extends QueryMethod {
|
||||
|
||||
private final Session session;
|
||||
private final Method method;
|
||||
private final Query queryAnnotation;
|
||||
private final Integer queryDepthParamIndex;
|
||||
private final Integer queryDepth;
|
||||
private boolean staticDepth;
|
||||
private final Session session;
|
||||
private final Method method;
|
||||
private final Query queryAnnotation;
|
||||
private final Integer queryDepthParamIndex;
|
||||
private final Integer queryDepth;
|
||||
private boolean staticDepth;
|
||||
|
||||
public GraphQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory, Session session) {
|
||||
super(method, metadata, factory);
|
||||
this.method = method;
|
||||
this.session = session;
|
||||
this.queryAnnotation = method.getAnnotation(Query.class);
|
||||
this.queryDepthParamIndex = getQueryDepthParamIndex(method);
|
||||
this.queryDepth = getStaticQueryDepth(method);
|
||||
if (queryDepth!=null && queryDepthParamIndex!=null) {
|
||||
throw new IllegalArgumentException(method.getName() + " cannot have both a method @Depth and a parameter @Depth");
|
||||
}
|
||||
public GraphQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory, Session session) {
|
||||
super(method, metadata, factory);
|
||||
this.method = method;
|
||||
this.session = session;
|
||||
this.queryAnnotation = method.getAnnotation(Query.class);
|
||||
this.queryDepthParamIndex = getQueryDepthParamIndex(method);
|
||||
this.queryDepth = getStaticQueryDepth(method);
|
||||
if (queryDepth != null && queryDepthParamIndex != null) {
|
||||
throw new IllegalArgumentException(method.getName() + " cannot have both a method @Depth and a parameter @Depth");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return queryAnnotation.value();
|
||||
}
|
||||
public String getQuery() {
|
||||
return queryAnnotation.value();
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamedQueryName() {
|
||||
throw new UnsupportedOperationException("OGM does not currently support named queries.");
|
||||
}
|
||||
@Override
|
||||
public String getNamedQueryName() {
|
||||
throw new UnsupportedOperationException("OGM does not currently support named queries.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The concrete, non-generic return type of this query method - i.e., the type to which graph database query results
|
||||
* should be mapped
|
||||
*/
|
||||
public Class<?> resolveConcreteReturnType() {
|
||||
Class<?> type = this.method.getReturnType();
|
||||
Type genericType = this.method.getGenericReturnType();
|
||||
/**
|
||||
* @return The concrete, non-generic return type of this query method - i.e., the type to which graph database query
|
||||
* results should be mapped
|
||||
*/
|
||||
public Class<?> resolveConcreteReturnType() {
|
||||
Class<?> type = this.method.getReturnType();
|
||||
Type genericType = this.method.getGenericReturnType();
|
||||
|
||||
if (Iterable.class.isAssignableFrom(type)) {
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType returnType = (ParameterizedType) genericType;
|
||||
Type componentType = returnType.getActualTypeArguments()[0];
|
||||
if (Iterable.class.isAssignableFrom(type)) {
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType returnType = (ParameterizedType) genericType;
|
||||
Type componentType = returnType.getActualTypeArguments()[0];
|
||||
|
||||
if (componentType instanceof TypeVariable) {
|
||||
return this.getDomainClass();
|
||||
}
|
||||
return componentType instanceof ParameterizedType ?
|
||||
(Class<?>) ((ParameterizedType) componentType).getRawType() :
|
||||
(Class<?>) componentType;
|
||||
} else {
|
||||
return Object.class;
|
||||
}
|
||||
}
|
||||
if (componentType instanceof TypeVariable) {
|
||||
return this.getDomainClass();
|
||||
}
|
||||
return componentType instanceof ParameterizedType ? (Class<?>) ((ParameterizedType) componentType).getRawType()
|
||||
: (Class<?>) componentType;
|
||||
} else {
|
||||
return Object.class;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public RepositoryQuery createQuery() {
|
||||
if (method.getAnnotation(Query.class) != null) {
|
||||
if (resolveConcreteReturnType().isAnnotationPresent(QueryResult.class)) {
|
||||
return new QueryResultGraphRepositoryQuery(this, session);
|
||||
}
|
||||
return new GraphRepositoryQuery(this, session);
|
||||
}
|
||||
return new DerivedGraphRepositoryQuery(this, session);
|
||||
public RepositoryQuery createQuery() {
|
||||
if (method.getAnnotation(Query.class) != null) {
|
||||
if (resolveConcreteReturnType().isAnnotationPresent(QueryResult.class)) {
|
||||
return new QueryResultGraphRepositoryQuery(this, session);
|
||||
}
|
||||
return new GraphRepositoryQuery(this, session);
|
||||
}
|
||||
return new DerivedGraphRepositoryQuery(this, session);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getQueryDepthParamIndex() {
|
||||
return queryDepthParamIndex;
|
||||
}
|
||||
public Integer getQueryDepthParamIndex() {
|
||||
return queryDepthParamIndex;
|
||||
}
|
||||
|
||||
public Integer getQueryDepth() {
|
||||
return queryDepth;
|
||||
}
|
||||
public Integer getQueryDepth() {
|
||||
return queryDepth;
|
||||
}
|
||||
|
||||
public boolean hasStaticDepth() {
|
||||
return staticDepth;
|
||||
}
|
||||
public boolean hasStaticDepth() {
|
||||
return staticDepth;
|
||||
}
|
||||
|
||||
private Integer getQueryDepthParamIndex(Method method) {
|
||||
Annotation[][] annotations = method.getParameterAnnotations();
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
if (annotations[i].length > 0) {
|
||||
for (Annotation annotation : annotations[i]) {
|
||||
if (annotation.annotationType() == Depth.class) {
|
||||
if (method.getParameterTypes()[i] == Integer.class || method.getParameterTypes()[i] == int.class) {
|
||||
return i;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
//Java 8 only
|
||||
Parameter[] parameters = method.getParameters();
|
||||
for (int i = 0; i < method.getParameterCount(); i++) {
|
||||
if (parameters[i].isAnnotationPresent(Depth.class)) {
|
||||
if (parameters[i].getType() == Integer.class || parameters[i].getType() == int.class) {
|
||||
return i;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
private Integer getQueryDepthParamIndex(Method method) {
|
||||
Annotation[][] annotations = method.getParameterAnnotations();
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
if (annotations[i].length > 0) {
|
||||
for (Annotation annotation : annotations[i]) {
|
||||
if (annotation.annotationType() == Depth.class) {
|
||||
if (method.getParameterTypes()[i] == Integer.class || method.getParameterTypes()[i] == int.class) {
|
||||
return i;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
//Java 8 only
|
||||
Parameter[] parameters = method.getParameters();
|
||||
for (int i = 0; i < method.getParameterCount(); i++) {
|
||||
if (parameters[i].isAnnotationPresent(Depth.class)) {
|
||||
if (parameters[i].getType() == Integer.class || parameters[i].getType() == int.class) {
|
||||
return i;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
|
||||
private Integer getStaticQueryDepth(Method method) {
|
||||
if (method.isAnnotationPresent(Depth.class)) {
|
||||
staticDepth = true;
|
||||
return method.getAnnotation(Depth.class).value();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private Integer getStaticQueryDepth(Method method) {
|
||||
if (method.isAnnotationPresent(Depth.class)) {
|
||||
staticDepth = true;
|
||||
return method.getAnnotation(Depth.class).value();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public String getCountQueryString() {
|
||||
return queryAnnotation != null ? queryAnnotation.countQuery() : null;
|
||||
}
|
||||
public String getCountQueryString() {
|
||||
return queryAnnotation != null ? queryAnnotation.countQuery() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.query;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -21,7 +20,10 @@ import java.util.Map;
|
||||
import org.neo4j.ogm.model.QueryStatistics;
|
||||
import org.neo4j.ogm.model.Result;
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.SliceImpl;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
@@ -30,7 +32,6 @@ import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Specialisation of {@link RepositoryQuery} that handles mapping to object annotated with <code>@Query</code>.
|
||||
*
|
||||
@@ -64,12 +65,11 @@ public class GraphRepositoryQuery implements RepositoryQuery {
|
||||
ResultProcessor processor = graphQueryMethod.getResultProcessor();
|
||||
Object result = execute(returnType, concreteType, getQueryString(), params, accessor);
|
||||
|
||||
return Result.class.equals(returnType) ? result :
|
||||
processor.withDynamicProjection(accessor).processResult(result);
|
||||
return Result.class.equals(returnType) ? result : processor.withDynamicProjection(accessor).processResult(result);
|
||||
}
|
||||
|
||||
protected Object execute(Class<?> returnType, Class<?> concreteType, String cypherQuery,
|
||||
Map<String, Object> queryParams, ParameterAccessor parameterAccessor) {
|
||||
Map<String, Object> queryParams, ParameterAccessor parameterAccessor) {
|
||||
|
||||
Pageable pageable = parameterAccessor.getPageable();
|
||||
Sort sort = parameterAccessor.getSort();
|
||||
@@ -77,7 +77,7 @@ public class GraphRepositoryQuery implements RepositoryQuery {
|
||||
sort = pageable.getSort();
|
||||
}
|
||||
if (sort != null) {
|
||||
//Custom queries in the OGM do not support pageable
|
||||
// Custom queries in the OGM do not support pageable
|
||||
cypherQuery = addSorting(cypherQuery, sort);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,6 @@ public class GraphRepositoryQuery implements RepositoryQuery {
|
||||
return getQueryMethod().getQuery();
|
||||
}
|
||||
|
||||
|
||||
protected Object createPage(GraphQueryMethod graphQueryMethod, List resultList, Pageable pageable, Long count) {
|
||||
if (pageable == null) {
|
||||
return graphQueryMethod.isPageQuery() ? new PageImpl(resultList) : new SliceImpl(resultList);
|
||||
@@ -116,15 +115,15 @@ public class GraphRepositoryQuery implements RepositoryQuery {
|
||||
currentTotal = count.intValue();
|
||||
} else {
|
||||
int pageOffset = pageable.getOffset();
|
||||
currentTotal = pageOffset + resultList.size() + (resultList.size() == pageable.getPageSize() ? pageable.getPageSize() : 0);
|
||||
currentTotal = pageOffset + resultList.size()
|
||||
+ (resultList.size() == pageable.getPageSize() ? pageable.getPageSize() : 0);
|
||||
}
|
||||
int resultWindowSize = Math.min(resultList.size(), pageable.getPageSize());
|
||||
boolean hasNext = resultWindowSize < resultList.size();
|
||||
List resultListPage = resultList.subList(0, resultWindowSize);
|
||||
|
||||
return graphQueryMethod.isPageQuery() ?
|
||||
new PageImpl(resultListPage, pageable, currentTotal) :
|
||||
new SliceImpl(resultListPage, pageable, hasNext);
|
||||
return graphQueryMethod.isPageQuery() ? new PageImpl(resultListPage, pageable, currentTotal)
|
||||
: new SliceImpl(resultListPage, pageable, hasNext);
|
||||
}
|
||||
|
||||
protected String addSorting(String baseQuery, Sort sort) {
|
||||
@@ -140,7 +139,7 @@ public class GraphRepositoryQuery implements RepositoryQuery {
|
||||
}
|
||||
|
||||
protected String addPaging(String cypherQuery, Map<String, Object> queryParams, int pageNumber, int pageSize) {
|
||||
//Custom queries in the OGM do not support pageable
|
||||
// Custom queries in the OGM do not support pageable
|
||||
cypherQuery = formatBaseQuery(cypherQuery);
|
||||
cypherQuery = cypherQuery + SKIP_LIMIT;
|
||||
queryParams.put(SKIP, pageNumber * pageSize);
|
||||
@@ -177,9 +176,9 @@ public class GraphRepositoryQuery implements RepositoryQuery {
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
Parameter parameter = methodParameters.getParameter(i);
|
||||
|
||||
//The parameter might be an entity, try to resolve its id
|
||||
// The parameter might be an entity, try to resolve its id
|
||||
Object parameterValue = session.resolveGraphIdFor(parameters[i]);
|
||||
if (parameterValue == null) { //Either not an entity or not persisted
|
||||
if (parameterValue == null) { // Either not an entity or not persisted
|
||||
parameterValue = parameters[i];
|
||||
}
|
||||
|
||||
@@ -192,7 +191,8 @@ public class GraphRepositoryQuery implements RepositoryQuery {
|
||||
return params;
|
||||
}
|
||||
|
||||
private Object mappedCollection(Class<?> concreteType, String cypherQuery, Map<String, Object> queryParams, Pageable pageable) {// Special method to handle SDN Iterable<Map<String, Object>> behaviour.
|
||||
private Object mappedCollection(Class<?> concreteType, String cypherQuery, Map<String, Object> queryParams,
|
||||
Pageable pageable) {// Special method to handle SDN Iterable<Map<String, Object>> behaviour.
|
||||
// TODO: Do we really want this method in an OGM? It's a little too low level and/or doesn't really fit.
|
||||
if (Map.class.isAssignableFrom(concreteType)) {
|
||||
return session.query(cypherQuery, queryParams).queryResults();
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.query;
|
||||
|
||||
|
||||
import static java.lang.reflect.Proxy.newProxyInstance;
|
||||
import static java.lang.reflect.Proxy.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -33,7 +32,8 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
/**
|
||||
* Specialisation of {@link GraphRepositoryQuery} that handles mapping to objects annotated with <code>@QueryResult</code>.
|
||||
* Specialisation of {@link GraphRepositoryQuery} that handles mapping to objects annotated with
|
||||
* <code>@QueryResult</code>.
|
||||
*
|
||||
* @author Adam George
|
||||
* @author Luanne Misquitta
|
||||
@@ -53,7 +53,7 @@ public class QueryResultGraphRepositoryQuery extends GraphRepositoryQuery {
|
||||
|
||||
@Override
|
||||
protected Object execute(Class<?> returnType, final Class<?> concreteReturnType, String cypherQuery,
|
||||
Map<String, Object> queryParams, ParameterAccessor parameterAccessor) {
|
||||
Map<String, Object> queryParams, ParameterAccessor parameterAccessor) {
|
||||
|
||||
Pageable pageable = parameterAccessor.getPageable();
|
||||
Sort sort = parameterAccessor.getSort();
|
||||
@@ -61,7 +61,7 @@ public class QueryResultGraphRepositoryQuery extends GraphRepositoryQuery {
|
||||
sort = pageable.getSort();
|
||||
}
|
||||
if (sort != null) {
|
||||
//Custom queries in the OGM do not support pageable
|
||||
// Custom queries in the OGM do not support pageable
|
||||
cypherQuery = addSorting(cypherQuery, sort);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public class QueryResultGraphRepositoryQuery extends GraphRepositoryQuery {
|
||||
}
|
||||
|
||||
private Object mapToConcreteType(final Class<?> targetType, final String cypherQuery,
|
||||
final Map<String, Object> queryParams, Pageable pageable) {
|
||||
final Map<String, Object> queryParams, Pageable pageable) {
|
||||
|
||||
if (graphQueryMethod.isPageQuery() || graphQueryMethod.isSliceQuery()) {
|
||||
final String query = addPaging(cypherQuery, queryParams, pageable.getPageNumber(), pageable.getPageSize());
|
||||
@@ -90,7 +90,7 @@ public class QueryResultGraphRepositoryQuery extends GraphRepositoryQuery {
|
||||
}
|
||||
|
||||
private Object mapToProxy(Class<?> targetType, String cypherQuery, Map<String, Object> queryParams,
|
||||
Pageable pageable) {
|
||||
Pageable pageable) {
|
||||
if (graphQueryMethod.isPageQuery() || graphQueryMethod.isSliceQuery()) {
|
||||
final String query = addPaging(cypherQuery, queryParams, pageable.getPageNumber(), pageable.getPageSize());
|
||||
List<Object> objects = mappedProxyResults(targetType, this.session.query(query, queryParams));
|
||||
@@ -100,7 +100,8 @@ public class QueryResultGraphRepositoryQuery extends GraphRepositoryQuery {
|
||||
}
|
||||
}
|
||||
|
||||
private List mappedConcreteResults(final Class<?> targetType, final String query, final Map<String, Object> queryParams) {
|
||||
private List mappedConcreteResults(final Class<?> targetType, final String query,
|
||||
final Map<String, Object> queryParams) {
|
||||
return (List) this.session.doInTransaction(new GraphCallback<Collection<Object>>() {
|
||||
@Override
|
||||
public Collection<Object> apply(Request requestHandler, Transaction transaction, MetaData metaData) {
|
||||
@@ -117,7 +118,7 @@ public class QueryResultGraphRepositoryQuery extends GraphRepositoryQuery {
|
||||
|
||||
private List mappedProxyResults(Class<?> targetType, Iterable<Map<String, Object>> queryResults) {
|
||||
List<Object> resultObjects = new ArrayList<>();
|
||||
Class<?>[] interfaces = new Class<?>[]{targetType};
|
||||
Class<?>[] interfaces = new Class<?>[] { targetType };
|
||||
for (Map<String, Object> map : queryResults) {
|
||||
resultObjects.add(newProxyInstance(targetType.getClassLoader(), interfaces, new QueryResultProxy(map)));
|
||||
}
|
||||
|
||||
@@ -13,17 +13,17 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.query;
|
||||
|
||||
import org.neo4j.ogm.annotation.Property;
|
||||
import org.neo4j.ogm.session.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.neo4j.ogm.annotation.Property;
|
||||
import org.neo4j.ogm.session.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Method {@link InvocationHandler} used for proxy objects that implement arbitrary interfaces annotated with
|
||||
* <code>@QueryResult</code>.
|
||||
@@ -32,41 +32,41 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
class QueryResultProxy implements InvocationHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(QueryResultProxy.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(QueryResultProxy.class);
|
||||
|
||||
private static final Pattern beanGetterPattern = Pattern.compile("^(is|get)(\\w+)");
|
||||
private static final Pattern beanGetterPattern = Pattern.compile("^(is|get)(\\w+)");
|
||||
|
||||
private final Map<String, ?> data;
|
||||
private final Map<String, ?> data;
|
||||
|
||||
QueryResultProxy(Map<String, ?> queryResults) {
|
||||
this.data = queryResults;
|
||||
}
|
||||
QueryResultProxy(Map<String, ?> queryResults) {
|
||||
this.data = queryResults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (isNotTraditionalGetter(method)) {
|
||||
log.warn("QueryResult interface method " + method.getName()
|
||||
+ " doesn't appear to be a getter and therefore may not return the correct result.");
|
||||
}
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (isNotTraditionalGetter(method)) {
|
||||
log.warn("QueryResult interface method " + method.getName()
|
||||
+ " doesn't appear to be a getter and therefore may not return the correct result.");
|
||||
}
|
||||
|
||||
if (method.isAnnotationPresent(Property.class)) {
|
||||
Property annotation = method.getAnnotation(Property.class);
|
||||
return Utils.coerceTypes(method.getReturnType(), data.get(annotation.name()));
|
||||
}
|
||||
if (method.isAnnotationPresent(Property.class)) {
|
||||
Property annotation = method.getAnnotation(Property.class);
|
||||
return Utils.coerceTypes(method.getReturnType(), data.get(annotation.name()));
|
||||
}
|
||||
|
||||
Matcher matcher = beanGetterPattern.matcher(method.getName());
|
||||
if (matcher.matches()) {
|
||||
String propertyKey = matcher.group(2);
|
||||
propertyKey = propertyKey.substring(0, 1).toLowerCase().concat(propertyKey.substring(1));
|
||||
return Utils.coerceTypes(method.getReturnType(),data.get(propertyKey));
|
||||
}
|
||||
Matcher matcher = beanGetterPattern.matcher(method.getName());
|
||||
if (matcher.matches()) {
|
||||
String propertyKey = matcher.group(2);
|
||||
propertyKey = propertyKey.substring(0, 1).toLowerCase().concat(propertyKey.substring(1));
|
||||
return Utils.coerceTypes(method.getReturnType(), data.get(propertyKey));
|
||||
}
|
||||
|
||||
return Utils.coerceTypes(method.getReturnType(), data.get(method.getName()));
|
||||
}
|
||||
return Utils.coerceTypes(method.getReturnType(), data.get(method.getName()));
|
||||
}
|
||||
|
||||
private boolean isNotTraditionalGetter(Method method) {
|
||||
return method.getParameterTypes().length != 0 || Void.class.equals(method.getReturnType())
|
||||
|| (!method.getName().startsWith("get") && !method.getName().startsWith("is"));
|
||||
}
|
||||
private boolean isNotTraditionalGetter(Method method) {
|
||||
return method.getParameterTypes().length != 0 || Void.class.equals(method.getReturnType())
|
||||
|| (!method.getName().startsWith("get") && !method.getName().startsWith("is"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,11 +12,21 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.repository.query.derived;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.neo4j.ogm.cypher.BooleanOperator;
|
||||
import org.neo4j.ogm.cypher.Filter;
|
||||
import org.springframework.data.neo4j.repository.query.derived.builder.*;
|
||||
import org.springframework.data.neo4j.repository.query.derived.builder.BetweenComparisonBuilder;
|
||||
import org.springframework.data.neo4j.repository.query.derived.builder.BooleanComparisonBuilder;
|
||||
import org.springframework.data.neo4j.repository.query.derived.builder.DistanceComparisonBuilder;
|
||||
import org.springframework.data.neo4j.repository.query.derived.builder.ExistsFilterBuilder;
|
||||
import org.springframework.data.neo4j.repository.query.derived.builder.FilterBuilder;
|
||||
import org.springframework.data.neo4j.repository.query.derived.builder.IsNullFilterBuilder;
|
||||
import org.springframework.data.neo4j.repository.query.derived.builder.PropertyComparisonBuilder;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
|
||||
/**
|
||||
@@ -28,64 +38,64 @@ import org.springframework.data.repository.query.parser.Part;
|
||||
*/
|
||||
public class CypherFinderQuery implements DerivedQueryDefinition {
|
||||
|
||||
private Class<?> entityType;
|
||||
private Part basePart;
|
||||
private List<FilterBuilder> filterBuilders = new ArrayList<>();
|
||||
private Class<?> entityType;
|
||||
private Part basePart;
|
||||
private List<FilterBuilder> filterBuilders = new ArrayList<>();
|
||||
|
||||
CypherFinderQuery(Class<?> entityType, Part basePart) {
|
||||
this.entityType = entityType;
|
||||
this.basePart = basePart;
|
||||
}
|
||||
CypherFinderQuery(Class<?> entityType, Part basePart) {
|
||||
this.entityType = entityType;
|
||||
this.basePart = basePart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Part getBasePart() { //because the OR is handled in a weird way. Luanne, explain better
|
||||
return basePart;
|
||||
}
|
||||
@Override
|
||||
public Part getBasePart() { // because the OR is handled in a weird way. Luanne, explain better
|
||||
return basePart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Filter> getFilters(Map<Integer, Object> params) {
|
||||
@Override
|
||||
public List<Filter> getFilters(Map<Integer, Object> params) {
|
||||
|
||||
// buiding a stack of parameter values, so that the builders can pull them
|
||||
// according to their needs (zero, one or more parameters)
|
||||
// avoids to manage a current parameter index state here.
|
||||
Stack<Object> parametersStack = new Stack<>();
|
||||
if (!params.isEmpty()) {
|
||||
Integer maxParameterIndex = Collections.max(params.keySet());
|
||||
for (int i = 0; i <= maxParameterIndex; i++) {
|
||||
parametersStack.add(0, params.get(i));
|
||||
}
|
||||
}
|
||||
// buiding a stack of parameter values, so that the builders can pull them
|
||||
// according to their needs (zero, one or more parameters)
|
||||
// avoids to manage a current parameter index state here.
|
||||
Stack<Object> parametersStack = new Stack<>();
|
||||
if (!params.isEmpty()) {
|
||||
Integer maxParameterIndex = Collections.max(params.keySet());
|
||||
for (int i = 0; i <= maxParameterIndex; i++) {
|
||||
parametersStack.add(0, params.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
List<Filter> filters = new ArrayList<>();
|
||||
for (FilterBuilder filterBuilder : filterBuilders) {
|
||||
filters.addAll(filterBuilder.build(parametersStack));
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
List<Filter> filters = new ArrayList<>();
|
||||
for (FilterBuilder filterBuilder : filterBuilders) {
|
||||
filters.addAll(filterBuilder.build(parametersStack));
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPart(Part part, BooleanOperator booleanOperator) {
|
||||
@Override
|
||||
public void addPart(Part part, BooleanOperator booleanOperator) {
|
||||
|
||||
FilterBuilder builder = builderForPart(part, booleanOperator);
|
||||
filterBuilders.add(builder);
|
||||
}
|
||||
FilterBuilder builder = builderForPart(part, booleanOperator);
|
||||
filterBuilders.add(builder);
|
||||
}
|
||||
|
||||
private FilterBuilder builderForPart(Part part, BooleanOperator booleanOperator) {
|
||||
switch (part.getType()) {
|
||||
case NEAR:
|
||||
return new DistanceComparisonBuilder(part, booleanOperator, entityType);
|
||||
case BETWEEN:
|
||||
return new BetweenComparisonBuilder(part, booleanOperator, entityType);
|
||||
case IS_NULL:
|
||||
case IS_NOT_NULL:
|
||||
return new IsNullFilterBuilder(part, booleanOperator, entityType);
|
||||
case EXISTS:
|
||||
return new ExistsFilterBuilder(part, booleanOperator, entityType);
|
||||
case TRUE:
|
||||
case FALSE:
|
||||
return new BooleanComparisonBuilder(part, booleanOperator, entityType);
|
||||
default:
|
||||
return new PropertyComparisonBuilder(part, booleanOperator, entityType);
|
||||
}
|
||||
}
|
||||
private FilterBuilder builderForPart(Part part, BooleanOperator booleanOperator) {
|
||||
switch (part.getType()) {
|
||||
case NEAR:
|
||||
return new DistanceComparisonBuilder(part, booleanOperator, entityType);
|
||||
case BETWEEN:
|
||||
return new BetweenComparisonBuilder(part, booleanOperator, entityType);
|
||||
case IS_NULL:
|
||||
case IS_NOT_NULL:
|
||||
return new IsNullFilterBuilder(part, booleanOperator, entityType);
|
||||
case EXISTS:
|
||||
return new ExistsFilterBuilder(part, booleanOperator, entityType);
|
||||
case TRUE:
|
||||
case FALSE:
|
||||
return new BooleanComparisonBuilder(part, booleanOperator, entityType);
|
||||
default:
|
||||
return new PropertyComparisonBuilder(part, booleanOperator, entityType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.query.derived;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.neo4j.ogm.cypher.Filters;
|
||||
import org.neo4j.ogm.cypher.query.Pagination;
|
||||
@@ -89,7 +93,7 @@ public class DerivedGraphRepositoryQuery implements RepositoryQuery {
|
||||
}
|
||||
return session.count(info.getJavaType(), filters);
|
||||
} else {
|
||||
throw new RuntimeException("Long is required as the return type of a Count query");
|
||||
throw new RuntimeException("Long is required as the return type of a Count query");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +179,13 @@ public class DerivedGraphRepositoryQuery implements RepositoryQuery {
|
||||
return graphQueryMethod;
|
||||
}
|
||||
|
||||
private List queryResults(Class<?> concreteType, int queryDepth, Filters params, PagingAndSorting pagingAndSorting) {
|
||||
private List queryResults(Class<?> concreteType, int queryDepth, Filters params,
|
||||
PagingAndSorting pagingAndSorting) {
|
||||
List resultList;
|
||||
switch (pagingAndSorting.configuration()) {
|
||||
case PagingAndSorting.PAGING_AND_SORTING:
|
||||
resultList = (List) session.loadAll(concreteType, params, pagingAndSorting.sortOrder, pagingAndSorting.pagination, queryDepth);
|
||||
resultList = (List) session.loadAll(concreteType, params, pagingAndSorting.sortOrder,
|
||||
pagingAndSorting.pagination, queryDepth);
|
||||
break;
|
||||
|
||||
case PagingAndSorting.PAGING_ONLY:
|
||||
@@ -213,15 +219,14 @@ public class DerivedGraphRepositoryQuery implements RepositoryQuery {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public QueryMethod getQueryMethod() {
|
||||
return graphQueryMethod;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets values from parameters supplied by the finder on {@link org.neo4j.ogm.cypher.Filter} built by the {@link GraphQueryMethod}
|
||||
* Sets values from parameters supplied by the finder on {@link org.neo4j.ogm.cypher.Filter} built by the
|
||||
* {@link GraphQueryMethod}
|
||||
*
|
||||
* @param parameters parameter values supplied by the finder method
|
||||
* @return List of Parameter with values set
|
||||
@@ -239,22 +244,19 @@ public class DerivedGraphRepositoryQuery implements RepositoryQuery {
|
||||
return new Filters(queryDefinition.getFilters(params));
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected Object createPage(GraphQueryMethod graphQueryMethod, List resultList, Pageable pageable) {
|
||||
if (pageable == null) {
|
||||
return graphQueryMethod.isPageQuery() ? new PageImpl(resultList) : new SliceImpl(resultList);
|
||||
}
|
||||
int currentTotal = pageable.getOffset() + resultList.size() +
|
||||
(resultList.size() == pageable.getPageSize() ? pageable.getPageSize() : 0);
|
||||
int currentTotal = pageable.getOffset() + resultList.size()
|
||||
+ (resultList.size() == pageable.getPageSize() ? pageable.getPageSize() : 0);
|
||||
|
||||
int resultWindowSize = Math.min(resultList.size(), pageable.getPageSize());
|
||||
boolean hasNext = resultWindowSize < resultList.size();
|
||||
List resultListPage = resultList.subList(0, resultWindowSize);
|
||||
|
||||
return graphQueryMethod.isPageQuery() ?
|
||||
new PageImpl(resultListPage, pageable, currentTotal) :
|
||||
new SliceImpl(resultListPage, pageable, hasNext);
|
||||
return graphQueryMethod.isPageQuery() ? new PageImpl(resultListPage, pageable, currentTotal)
|
||||
: new SliceImpl(resultListPage, pageable, hasNext);
|
||||
}
|
||||
|
||||
private SortOrder convert(Sort sort) {
|
||||
@@ -290,7 +292,9 @@ public class DerivedGraphRepositoryQuery implements RepositoryQuery {
|
||||
if (graphQueryMethod.isPageQuery() || graphQueryMethod.isSliceQuery()) {
|
||||
if (graphQueryMethod.isSliceQuery()) {
|
||||
pagination = new Pagination(pageable.getPageNumber(), pageable.getPageSize() + 1);
|
||||
pagination.setOffset(pageable.getPageNumber() * pageable.getPageSize()); //For a slice, need one extra result to determine if there is a next page
|
||||
pagination.setOffset(pageable.getPageNumber() * pageable.getPageSize()); // For a slice, need one extra result
|
||||
// to determine if there is a next
|
||||
// page
|
||||
} else {
|
||||
pagination = new Pagination(pageable.getPageNumber(), pageable.getPageSize());
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ public class DerivedQueryBuilder {
|
||||
|
||||
/**
|
||||
* Add a part as a parameter to the graph query.
|
||||
*
|
||||
* @param part the Part to be added
|
||||
* @param booleanOperator the {@link BooleanOperator} to be used when appending the parameter to the query.
|
||||
*/
|
||||
@@ -40,6 +41,7 @@ public class DerivedQueryBuilder {
|
||||
|
||||
/**
|
||||
* Add criteria from an intermediate builder to the query
|
||||
*
|
||||
* @param fromBuilder the intermediate builder
|
||||
* @param booleanOperator the {@link BooleanOperator} to be used when appending the criteria to the query
|
||||
*/
|
||||
@@ -49,6 +51,7 @@ public class DerivedQueryBuilder {
|
||||
|
||||
/**
|
||||
* Builds the final query
|
||||
*
|
||||
* @return the final query
|
||||
*/
|
||||
public DerivedQueryDefinition buildQuery() {
|
||||
|
||||
@@ -11,17 +11,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.data.neo4j.repository.query.derived;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.neo4j.ogm.cypher.BooleanOperator;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An {@link AbstractQueryCreator} that builds a graph query.
|
||||
*
|
||||
|
||||
@@ -21,9 +21,8 @@ import org.neo4j.ogm.cypher.Filter;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
|
||||
/**
|
||||
* The graph query created based on a derived query.
|
||||
* The graph query created based on a derived query. /**
|
||||
*
|
||||
/**
|
||||
* @author Luanne Misquitta
|
||||
* @author Nicolas Mervaillie
|
||||
*/
|
||||
@@ -31,19 +30,22 @@ public interface DerivedQueryDefinition {
|
||||
|
||||
/**
|
||||
* Add a part as a parameter to the graph query.
|
||||
* @param part the Part to be added
|
||||
*
|
||||
* @param part the Part to be added
|
||||
* @param booleanOperator the {@link BooleanOperator} to be used when appending the parameter to the query.
|
||||
*/
|
||||
void addPart(Part part, BooleanOperator booleanOperator);
|
||||
|
||||
/**
|
||||
* Get the base part i.e. the first parameter of the graph query.
|
||||
*
|
||||
* @return Part representing the base of the query.
|
||||
*/
|
||||
Part getBasePart();
|
||||
|
||||
/**
|
||||
* Gets all cypher filters for this query
|
||||
*
|
||||
* @return The OGM filters with bound parameter values
|
||||
*/
|
||||
List<Filter> getFilters(Map<Integer, Object> params);
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.data.neo4j.repository.query.derived.builder;
|
||||
|
||||
import static org.springframework.data.repository.query.parser.Part.Type.*;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.data.neo4j.repository.query.derived.builder;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -54,7 +53,8 @@ public class DistanceComparisonBuilder extends FilterBuilder {
|
||||
distance = (Distance) secondArg;
|
||||
point = (Point) firstArg;
|
||||
} else {
|
||||
throw new IllegalArgumentException("findNear requires an argument of type Distance and an argument of type Point");
|
||||
throw new IllegalArgumentException(
|
||||
"findNear requires an argument of type Distance and an argument of type Point");
|
||||
}
|
||||
|
||||
double meters;
|
||||
@@ -66,7 +66,8 @@ public class DistanceComparisonBuilder extends FilterBuilder {
|
||||
meters = distance.getValue();
|
||||
}
|
||||
|
||||
DistanceFromPoint distanceFromPoint = new DistanceFromPoint(point.getX(), point.getY(), distance.getValue() * meters);
|
||||
DistanceFromPoint distanceFromPoint = new DistanceFromPoint(point.getX(), point.getY(),
|
||||
distance.getValue() * meters);
|
||||
DistanceComparison distanceComparison = new DistanceComparison(distanceFromPoint);
|
||||
|
||||
Filter filter = new Filter();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.springframework.data.neo4j.repository.query.derived.builder;
|
||||
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.data.neo4j.repository.query.derived.builder;
|
||||
|
||||
import static org.springframework.data.repository.query.parser.Part.Type.*;
|
||||
@@ -31,21 +30,21 @@ import org.springframework.data.repository.query.parser.Part;
|
||||
*/
|
||||
public class IsNullFilterBuilder extends FilterBuilder {
|
||||
|
||||
public IsNullFilterBuilder(Part part, BooleanOperator booleanOperator, Class<?> entityType) {
|
||||
super(part, booleanOperator, entityType);
|
||||
}
|
||||
public IsNullFilterBuilder(Part part, BooleanOperator booleanOperator, Class<?> entityType) {
|
||||
super(part, booleanOperator, entityType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Filter> build(Stack<Object> params) {
|
||||
Filter filter = new Filter();
|
||||
filter.setPropertyName(propertyName());
|
||||
filter.setOwnerEntityType(entityType);
|
||||
filter.setBooleanOperator(booleanOperator);
|
||||
filter.setNegated(isNegated() || part.getType() == IS_NOT_NULL);
|
||||
filter.setComparisonOperator(ComparisonOperator.IS_NULL);
|
||||
setNestedAttributes(part, filter);
|
||||
@Override
|
||||
public List<Filter> build(Stack<Object> params) {
|
||||
Filter filter = new Filter();
|
||||
filter.setPropertyName(propertyName());
|
||||
filter.setOwnerEntityType(entityType);
|
||||
filter.setBooleanOperator(booleanOperator);
|
||||
filter.setNegated(isNegated() || part.getType() == IS_NOT_NULL);
|
||||
filter.setComparisonOperator(ComparisonOperator.IS_NULL);
|
||||
setNestedAttributes(part, filter);
|
||||
|
||||
return Collections.singletonList(filter);
|
||||
}
|
||||
return Collections.singletonList(filter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ public class PropertyComparisonBuilder extends FilterBuilder {
|
||||
return Collections.singletonList(filter);
|
||||
}
|
||||
|
||||
|
||||
private ComparisonOperator convertToComparisonOperator(Part.Type type) {
|
||||
switch (type) {
|
||||
case AFTER:
|
||||
|
||||
@@ -13,47 +13,47 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.neo4j.ogm.MetaData;
|
||||
import org.neo4j.ogm.entity.io.EntityAccessManager;
|
||||
import org.neo4j.ogm.metadata.ClassInfo;
|
||||
import org.neo4j.ogm.metadata.FieldInfo;
|
||||
import org.springframework.data.repository.core.support.AbstractEntityInformation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
public class GraphEntityInformation<T, ID extends Serializable> extends AbstractEntityInformation<T, ID> {
|
||||
|
||||
private final MetaData metaData;
|
||||
private final MetaData metaData;
|
||||
|
||||
public GraphEntityInformation(MetaData metaData, Class<T> type) {
|
||||
super(type);
|
||||
this.metaData = metaData;
|
||||
}
|
||||
public GraphEntityInformation(MetaData metaData, Class<T> type) {
|
||||
super(type);
|
||||
this.metaData = metaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ID getId(T entity) {
|
||||
final ClassInfo classInfo = metaData.classInfo(getJavaType().getName());
|
||||
final FieldInfo primaryIndex = classInfo.primaryIndexField();
|
||||
@Override
|
||||
public ID getId(T entity) {
|
||||
final ClassInfo classInfo = metaData.classInfo(getJavaType().getName());
|
||||
final FieldInfo primaryIndex = classInfo.primaryIndexField();
|
||||
|
||||
if (primaryIndex != null) {
|
||||
return (ID) EntityAccessManager.getPropertyReader(classInfo, primaryIndex.getName()).readProperty(entity);
|
||||
}
|
||||
else {
|
||||
return (ID) EntityAccessManager.getPropertyReader(classInfo, classInfo.identityField().getName()).readProperty(entity);
|
||||
}
|
||||
}
|
||||
if (primaryIndex != null) {
|
||||
return (ID) EntityAccessManager.getPropertyReader(classInfo, primaryIndex.getName()).readProperty(entity);
|
||||
} else {
|
||||
return (ID) EntityAccessManager.getPropertyReader(classInfo, classInfo.identityField().getName())
|
||||
.readProperty(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ID> getIdType() {
|
||||
final FieldInfo primaryIndex = metaData.classInfo(getJavaType().getName()).primaryIndexField();
|
||||
@Override
|
||||
public Class<ID> getIdType() {
|
||||
final FieldInfo primaryIndex = metaData.classInfo(getJavaType().getName()).primaryIndexField();
|
||||
|
||||
if (primaryIndex != null) {
|
||||
return (Class<ID>) primaryIndex.convertedType();
|
||||
}
|
||||
return (Class<ID>) Long.class;
|
||||
}
|
||||
if (primaryIndex != null) {
|
||||
return (Class<ID>) primaryIndex.convertedType();
|
||||
}
|
||||
return (Class<ID>) Long.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ import org.springframework.data.neo4j.transaction.SessionFactoryUtils;
|
||||
*/
|
||||
public class Neo4jPersistenceExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return SessionFactoryUtils.convertOgmAccessException(ex);
|
||||
}
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return SessionFactoryUtils.convertOgmAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class Neo4jRepositoryFactory extends RepositoryFactorySupport {
|
||||
public <T, ID extends Serializable> EntityInformation<T, ID> getEntityInformation(Class<T> type) {
|
||||
Assert.notNull(type, "Domain class must not be null!");
|
||||
Assert.notNull(session, "Session must not be null!");
|
||||
return new GraphEntityInformation(((Neo4jSession)session).metaData(), type);
|
||||
return new GraphEntityInformation(((Neo4jSession) session).metaData(), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,7 +71,7 @@ public class Neo4jRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key,
|
||||
EvaluationContextProvider evaluationContextProvider) {
|
||||
EvaluationContextProvider evaluationContextProvider) {
|
||||
return new GraphQueryLookupStrategy(session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport
|
||||
import org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Special adapter for Springs {@link org.springframework.beans.factory.FactoryBean} interface to allow easy setup of
|
||||
* repository factories via Spring configuration.
|
||||
@@ -33,13 +32,14 @@ import org.springframework.util.Assert;
|
||||
* @author Luanne Misquitta
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
public class Neo4jRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
|
||||
public class Neo4jRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
|
||||
extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
|
||||
|
||||
private Session session;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link Neo4jRepositoryFactoryBean} for the given repository interface.
|
||||
*
|
||||
*
|
||||
* @param repositoryInterface must not be {@literal null}.
|
||||
*/
|
||||
public Neo4jRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
|
||||
@@ -81,5 +81,3 @@ public class Neo4jRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
|
||||
return new Neo4jRepositoryFactory(session);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,10 +18,8 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.neo4j.ogm.MetaData;
|
||||
import org.neo4j.ogm.cypher.query.Pagination;
|
||||
import org.neo4j.ogm.cypher.query.SortOrder;
|
||||
import org.neo4j.ogm.session.Neo4jSession;
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
@@ -37,7 +35,6 @@ import org.springframework.util.Assert;
|
||||
* you a more sophisticated interface than the plain {@link Session} .
|
||||
*
|
||||
* @param <T> the type of the entity to handle
|
||||
*
|
||||
* @author Vince Bickers
|
||||
* @author Luanne Misquitta
|
||||
* @author Mark Angrish
|
||||
@@ -199,7 +196,8 @@ public class SimpleNeo4jRepository<T, ID extends Serializable> implements Neo4jR
|
||||
|
||||
@Override
|
||||
public Page<T> findAll(Pageable pageable, int depth) {
|
||||
Collection<T> data = session.loadAll(clazz, convert(pageable.getSort()), new Pagination(pageable.getPageNumber(), pageable.getPageSize()), depth);
|
||||
Collection<T> data = session.loadAll(clazz, convert(pageable.getSort()),
|
||||
new Pagination(pageable.getPageNumber(), pageable.getPageSize()), depth);
|
||||
return updatePage(pageable, new ArrayList<T>(data));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,9 @@ package org.springframework.data.neo4j.template;
|
||||
import org.neo4j.ogm.session.Session;
|
||||
|
||||
/**
|
||||
* Callback interface for Neo4j OGM code. To be used with {@link Neo4jTemplate}'s
|
||||
* execution methods, often as anonymous classes within a method implementation.
|
||||
* A typical implementation will call {@code Session.load/find/update} to perform
|
||||
* some operations on persistent objects.
|
||||
* Callback interface for Neo4j OGM code. To be used with {@link Neo4jTemplate}'s execution methods, often as anonymous
|
||||
* classes within a method implementation. A typical implementation will call {@code Session.load/find/update} to
|
||||
* perform some operations on persistent objects.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @see Neo4jTemplate
|
||||
@@ -29,13 +28,12 @@ import org.neo4j.ogm.session.Session;
|
||||
public interface Neo4jCallback<T> {
|
||||
|
||||
/**
|
||||
* Gets called by {@code Neo4jTemplate.doExecute} with an active
|
||||
* OGM {@code Session}. Does not need to care about activating
|
||||
* or closing the {@code Session}, or handling transactions.
|
||||
* <p>Allows for returning a result object created within the callback,
|
||||
* i.e. a domain object or a collection of domain objects.
|
||||
* A thrown custom RuntimeException is treated as an application exception:
|
||||
* It gets propagated to the caller of the template.
|
||||
* Gets called by {@code Neo4jTemplate.doExecute} with an active OGM {@code Session}. Does not need to care about
|
||||
* activating or closing the {@code Session}, or handling transactions.
|
||||
* <p>
|
||||
* Allows for returning a result object created within the callback, i.e. a domain object or a collection of domain
|
||||
* objects. A thrown custom RuntimeException is treated as an application exception: It gets propagated to the caller
|
||||
* of the template.
|
||||
*
|
||||
* @param session active Neo4j session
|
||||
* @return a result object, or {@code null} if none
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package org.springframework.data.neo4j.template;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.neo4j.ogm.cypher.Filter;
|
||||
import org.neo4j.ogm.cypher.Filters;
|
||||
@@ -26,416 +28,427 @@ import org.neo4j.ogm.session.Session;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Spring Data operations interface, implemented by {@link Neo4jTemplate}, that provides the API for using
|
||||
* the persistence framework in a more direct way as an alternative to the repositories.
|
||||
* Spring Data operations interface, implemented by {@link Neo4jTemplate}, that provides the API for using the
|
||||
* persistence framework in a more direct way as an alternative to the repositories.
|
||||
*
|
||||
* @author Adam George
|
||||
* @author Luanne Misquitta
|
||||
* @author Mark Angrish
|
||||
*
|
||||
* @deprecated Use {@link org.neo4j.ogm.session.Session}
|
||||
*/
|
||||
@Repository
|
||||
@Deprecated
|
||||
public interface Neo4jOperations {
|
||||
|
||||
/**
|
||||
* Execute the action specified by the given action object within a
|
||||
* {@link Session}.
|
||||
* <p>Application exceptions thrown by the action object get propagated
|
||||
* to the caller (can only be unchecked). OGM exceptions are
|
||||
* transformed into appropriate DAO ones. Allows for returning a result
|
||||
* object, that is a domain object or a collection of domain objects.
|
||||
* <p>Note: Callback code is not supposed to handle transactions itself!
|
||||
* Use an appropriate transaction manager like
|
||||
* {@link org.springframework.data.neo4j.transaction.Neo4jTransactionManager}. Generally, callback code must not
|
||||
* touch any {@code Session} lifecycle methods, like close,
|
||||
* disconnect, or reconnect, to let the template do its work.
|
||||
* @param action callback object that specifies the OGM action
|
||||
* @return a result object returned by the action, or {@code null}
|
||||
* @see Session
|
||||
*/
|
||||
<T> T execute(Neo4jCallback<T> action) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Loads an entity of type T that matches the specified ID to the default depth.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param id The ID of the node or relationship to match
|
||||
* @return The instance of T loaded from the database that matches the specified ID or <code>null</code> if no match is found
|
||||
*/
|
||||
<T> T load(Class<T> type, Long id);
|
||||
|
||||
/**
|
||||
* Loads an entity of type T that matches the specified ID to the given depth.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param id The ID of the node or relationship to match
|
||||
* @param depth The maximum number of relationships away from the identified object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return The instance of T loaded from the database that matches the specified ID or <code>null</code> if no match is found
|
||||
*/
|
||||
<T> T load(Class<T> type, Long id, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the default depth.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if none
|
||||
* are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the specified depth.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if none
|
||||
* are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the specified depth, with Sorting.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param sortOrder The SortOrder to be applied
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if none
|
||||
* are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, SortOrder sortOrder, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the specified depth, with Sorting and Pagination.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param sortOrder The SortOrder to be applied
|
||||
* @param pagination The Pagination to be applied
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if none
|
||||
* are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, SortOrder sortOrder, Pagination pagination, int depth);
|
||||
|
||||
|
||||
/**
|
||||
* Reloads all of the entities which match IDs in the given {@link Collection} to the specified depth. Of course, this will
|
||||
* only work for persistent objects (i.e., those with a non-null <code>@GraphId</code> field).
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param ids The IDs of objects to re-hydrate
|
||||
* @param depth The depth to which the objects should be hydrated
|
||||
* @return A new {@link Collection} of entities matching those in the given collection hydrated to the given depth
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Collection<Long> ids, int depth);
|
||||
|
||||
/**
|
||||
* Reloads all of the entities in the given {@link Collection} to the specified depth. Of course, this will
|
||||
* only work for persistent objects (i.e., those with a non-null <code>@GraphId</code> field).
|
||||
*
|
||||
* @param objects The objects to re-hydrate
|
||||
* @param depth The depth to which the objects should be hydrated
|
||||
* @return A new {@link Collection} of entities matching those in the given collection hydrated to the given depth
|
||||
*/
|
||||
<T> Collection<T> loadAll(Collection<T> objects, int depth);
|
||||
|
||||
/**
|
||||
* Reloads all of the entities in the given {@link Collection} to the specified depth, sorted by the sprcified SortOrder Of course, this will
|
||||
* only work for persistent objects (i.e., those with a non-null <code>@GraphId</code> field).
|
||||
*
|
||||
* @param ids The IDs of objects to re-hydrate
|
||||
* @param sortOrder The SortOrder to be used
|
||||
* @param depth The depth to which the objects should be hydrated
|
||||
* @return A new {@link Collection} of entities matching those in the given collection hydrated to the given depth
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Collection<Long> ids, SortOrder sortOrder, int depth);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the default depth conforming to the specified
|
||||
* filter criteria.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param filter The filter to constrain entities with.
|
||||
* @return A {@link Collection} containing all matching instances of the given type in the database or an empty collection if none
|
||||
* are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Filter filter);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the specified depth, with Pagination.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param pagination The Pagination to be applied
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if none
|
||||
* are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Pagination pagination, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the default depth conforming to the specified
|
||||
* filter criteria.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param filter The filter to constrain entities with.
|
||||
* @param depth The depth to which the objects should be hydrated
|
||||
* @return A {@link Collection} containing all matching instances of the given type in the database or an empty collection if none
|
||||
* are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Filter filter, int depth);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains a property matching the given name with the given value.
|
||||
* This method assumes that the requested property/value combination will be unique for all entities of this type in
|
||||
* the database and will throw an exception unless exactly one result is found. If several entities are expected to
|
||||
* be returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @return The instance of T corresponding to the entity that matches the given property, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperty(Class<T> type, String propertyName, Object propertyValue);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains a property matching the given name with the given value.
|
||||
* This method assumes that the requested property/value combination will be unique for all entities of this type in
|
||||
* the database and will throw an exception unless exactly one result is found. If several entities are expected to
|
||||
* be returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return The instance of T corresponding to the entity that matches the given property, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperty(Class<T> type, String propertyName, Object propertyValue, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a property matching the given name with the given value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @return A {@link Collection} containing all the entities that match the given property or an empty {@link Collection} if
|
||||
* there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperty(Class<T> type, String propertyName, Object propertyValue);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a property matching the given name with the given value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return A {@link Collection} containing all the entities that match the given property or an empty {@link Collection} if
|
||||
* there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperty(Class<T> type, String propertyName, Object propertyValue, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains properties matching the ones supplied with given name and value.
|
||||
* This method assumes that the requested property/value combinations will be unique for all entities of this type in
|
||||
* the database and will throw an exception unless exactly one result is found. If several entities are expected to
|
||||
* be returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @return The instance of T corresponding to the entity that matches the given properties, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperties(Class<T> type, Filters parameters);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains properties matching the ones supplied with given name and value.
|
||||
* This method assumes that the requested property/value combinations will be unique for all entities of this type in
|
||||
* the database and will throw an exception unless exactly one result is found. If several entities are expected to
|
||||
* be returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return The instance of T corresponding to the entity that matches the given properties, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperties(Class<T> type, Filters parameters, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a properties matching the ones supplied with given name and value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @return A {@link Collection} containing all the entities that match the given properties or an empty {@link Collection} if
|
||||
* there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperties(Class<T> type, Filters parameters);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a properties matching the ones supplied with given name and value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return A {@link Collection} containing all the entities that match the given properties or an empty {@link Collection} if
|
||||
* there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperties(Class<T> type, Filters parameters, int depth);
|
||||
|
||||
/**
|
||||
* Saves the specified entity in the graph database. If the entity is currently transient then the persistent version of
|
||||
* the entity will be returned, containing its new graph ID.
|
||||
*
|
||||
* @param entity The entity to save
|
||||
* @return The saved entity
|
||||
*/
|
||||
<T> T save(T entity);
|
||||
|
||||
/**
|
||||
* Saves the specified entity in the graph database to a custom depth. If the entity is currently transient then the persistent version of
|
||||
* the entity will be returned, containing its new graph ID.
|
||||
*
|
||||
* @param entity The entity to save
|
||||
* @param depth The maximum number of relationships away from the entity to follow when saving related entities.
|
||||
* A value of 0 just saves the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return The saved entity
|
||||
*/
|
||||
<T> T save(T entity, int depth);
|
||||
|
||||
|
||||
/**
|
||||
* Removes the given node or relationship entity from the graph. The entity is first removed
|
||||
* from all indexes and then deleted.
|
||||
*
|
||||
* @param entity The entity to delete
|
||||
*/
|
||||
void delete(Object entity);
|
||||
/**
|
||||
* Execute the action specified by the given action object within a {@link Session}.
|
||||
* <p>
|
||||
* Application exceptions thrown by the action object get propagated to the caller (can only be unchecked). OGM
|
||||
* exceptions are transformed into appropriate DAO ones. Allows for returning a result object, that is a domain object
|
||||
* or a collection of domain objects.
|
||||
* <p>
|
||||
* Note: Callback code is not supposed to handle transactions itself! Use an appropriate transaction manager like
|
||||
* {@link org.springframework.data.neo4j.transaction.Neo4jTransactionManager}. Generally, callback code must not touch
|
||||
* any {@code Session} lifecycle methods, like close, disconnect, or reconnect, to let the template do its work.
|
||||
*
|
||||
* @param action callback object that specifies the OGM action
|
||||
* @return a result object returned by the action, or {@code null}
|
||||
* @see Session
|
||||
*/
|
||||
<T> T execute(Neo4jCallback<T> action) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Removes all nodes or relationship entities of a specific type from the graph.
|
||||
* @param type the type of entity to delete
|
||||
*/
|
||||
<T> void deleteAll(Class<T> type);
|
||||
* Loads an entity of type T that matches the specified ID to the default depth.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param id The ID of the node or relationship to match
|
||||
* @return The instance of T loaded from the database that matches the specified ID or <code>null</code> if no match
|
||||
* is found
|
||||
*/
|
||||
<T> T load(Class<T> type, Long id);
|
||||
|
||||
/**
|
||||
* Removes all mapping information from the current session
|
||||
*/
|
||||
void clear();
|
||||
/**
|
||||
* Loads an entity of type T that matches the specified ID to the given depth.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param id The ID of the node or relationship to match
|
||||
* @param depth The maximum number of relationships away from the identified object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return The instance of T loaded from the database that matches the specified ID or <code>null</code> if no match
|
||||
* is found
|
||||
*/
|
||||
<T> T load(Class<T> type, Long id, int depth);
|
||||
|
||||
/**
|
||||
* Executes the specified Cypher query with the given parameters against the underlying Neo4j database and returns the
|
||||
* row-based result in the form of an {@link Iterable} of {@link Map}s.
|
||||
* <p>
|
||||
* Each of the resultant maps corresponds to a "row" in the result set and the key set in each map contains all the names
|
||||
* contained in the <code>RETURN</code> clause of the given query.
|
||||
* </p>
|
||||
*
|
||||
* @param cypherQuery The Cypher query to execute
|
||||
* @param params The parameter to merge into the cypher query or an empty {@link Map} if the given query isn't parameterised
|
||||
* @return A {@link Query} containing an {@link Iterable} map representing query results and {@link QueryStatistics} if applicable.
|
||||
* @throws RuntimeException if the given query is not a valid Cypherquery
|
||||
*/
|
||||
Result query(String cypherQuery, Map<String, ?> params);
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the default depth.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if
|
||||
* none are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type);
|
||||
|
||||
/**
|
||||
* Runs the specified Cypher query with the given parameters against the underlying Neo4j database and returns the result
|
||||
* marshalled as an object of the requested type.
|
||||
*
|
||||
* @param entityType The {@link Class} denoting the type of entity to return
|
||||
* @param cypherQuery The Cypher query to execute
|
||||
* @param parameters The parameter to merge into the Cypher query or an empty {@link Map} if the query's not parameterised
|
||||
* @return An instance of T that corresponds to the entity found by executing the query or <code>null</code> if nothing is
|
||||
* found by the query
|
||||
* @throws RuntimeException If more than one result is returned or there's an issue executing the query
|
||||
*/
|
||||
<T> T queryForObject(Class<T> entityType, String cypherQuery, Map<String, ?> parameters);
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the specified depth.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if
|
||||
* none are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, int depth);
|
||||
|
||||
/**
|
||||
* Runs the specified Cypher query with the given parameters against the underlying Neo4j database and returns the result
|
||||
* marshalled as a group of objects of the requested type.
|
||||
*
|
||||
* @param entityType The {@link Class} denoting the type of entity to return
|
||||
* @param cypherQuery The Cypher query to execute
|
||||
* @param parameters The parameter to merge into the Cypher query or an empty {@link Map} if the query's not parameterised
|
||||
* @return An {@link Iterable} over the entities found by executing the query or an empty <code>Iterable</code> if nothing
|
||||
* is found by the query, never <code>null</code>
|
||||
* @throws RuntimeException If there's an issue executing the query
|
||||
*/
|
||||
<T> Iterable<T> queryForObjects(Class<T> entityType, String cypherQuery, Map<String, ?> parameters);
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the specified depth, with Sorting.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param sortOrder The SortOrder to be applied
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if
|
||||
* none are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, SortOrder sortOrder, int depth);
|
||||
|
||||
/**
|
||||
* Given a cypher statement this method will return a {@link Query} object containing a collection of Map's which represent Neo4j
|
||||
* objects as properties, along with query statistics if applicable.
|
||||
*
|
||||
* Each element of the query result is a map which you can access by the name of the returned field
|
||||
*
|
||||
* TODO: Are we going to use the neo4jOperations conversion method to cast the value object to its proper class?
|
||||
*
|
||||
* @param cypher The parametrisable cypher to execute.
|
||||
* @param parameters Any parameters to attach to the cypher.
|
||||
* @param readOnly true if the query is readOnly, false otherwise
|
||||
*
|
||||
* @return A {@link Query} of {@link Iterable}s with each entry representing a neo4j object's properties.
|
||||
*/
|
||||
Result query(String cypher, Map<String, ?> parameters, boolean readOnly);
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the specified depth, with Sorting and
|
||||
* Pagination.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param sortOrder The SortOrder to be applied
|
||||
* @param pagination The Pagination to be applied
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if
|
||||
* none are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, SortOrder sortOrder, Pagination pagination, int depth);
|
||||
|
||||
/**
|
||||
* Provides the instance count for the given <em>node</em> entity type. This method is also provided by the
|
||||
* corresponding repository.
|
||||
*
|
||||
* @param entityClass The {@link Class} representing the type of node entity to count
|
||||
* @return The number of entities in the database of the given type
|
||||
*/
|
||||
long count(Class<?> entityClass);
|
||||
/**
|
||||
* Reloads all of the entities which match IDs in the given {@link Collection} to the specified depth. Of course, this
|
||||
* will only work for persistent objects (i.e., those with a non-null <code>@GraphId</code> field).
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param ids The IDs of objects to re-hydrate
|
||||
* @param depth The depth to which the objects should be hydrated
|
||||
* @return A new {@link Collection} of entities matching those in the given collection hydrated to the given depth
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Collection<Long> ids, int depth);
|
||||
|
||||
/**
|
||||
* Reloads all of the entities in the given {@link Collection} to the specified depth. Of course, this will only work
|
||||
* for persistent objects (i.e., those with a non-null <code>@GraphId</code> field).
|
||||
*
|
||||
* @param objects The objects to re-hydrate
|
||||
* @param depth The depth to which the objects should be hydrated
|
||||
* @return A new {@link Collection} of entities matching those in the given collection hydrated to the given depth
|
||||
*/
|
||||
<T> Collection<T> loadAll(Collection<T> objects, int depth);
|
||||
|
||||
// /**
|
||||
// * Issue a single Cypher update operation (such as a <tt>CREATE</tt>, <tt>MERGE</tt> or <tt>DELETE</tt> statement).
|
||||
// *
|
||||
// * @deprecated Use {@link Neo4jOperations}.query() to return both results as well as query statistics.
|
||||
// * @param cypherQuery The Cypher query to execute
|
||||
// * @return {@link QueryStatistics} representing statistics about graph modifications as a result of the cypher execution.
|
||||
// */
|
||||
// @Deprecated
|
||||
// QueryStatistics execute(String cypherQuery);
|
||||
/**
|
||||
* Reloads all of the entities in the given {@link Collection} to the specified depth, sorted by the sprcified
|
||||
* SortOrder Of course, this will only work for persistent objects (i.e., those with a non-null <code>@GraphId</code>
|
||||
* field).
|
||||
*
|
||||
* @param ids The IDs of objects to re-hydrate
|
||||
* @param sortOrder The SortOrder to be used
|
||||
* @param depth The depth to which the objects should be hydrated
|
||||
* @return A new {@link Collection} of entities matching those in the given collection hydrated to the given depth
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Collection<Long> ids, SortOrder sortOrder, int depth);
|
||||
|
||||
// /**
|
||||
// * Allows a cypher statement with a modification statement to be executed.
|
||||
// *
|
||||
// * <p>Parameters may be scalars or domain objects themselves.</p>
|
||||
// * @deprecated Use {@link Neo4jOperations}.query() to return both results as well as query statistics.
|
||||
// * @param cypher The parametrisable cypher to execute.
|
||||
// * @param parameters Any parameters to attach to the cypher. These may be domain objects or scalars. Note that
|
||||
// * if a complex domain object is provided only the properties of that object will be set.
|
||||
// * If relationships of a provided object also need to be set then the cypher should reflect this
|
||||
// * and further domain object parameters provided.
|
||||
// *
|
||||
// * @return {@link QueryStatistics} representing statistics about graph modifications as a result of the cypher execution.
|
||||
// */
|
||||
// @Deprecated
|
||||
// QueryStatistics execute(String cypher, Map<String, Object> parameters);
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the default depth conforming to the
|
||||
* specified filter criteria.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param filter The filter to constrain entities with.
|
||||
* @return A {@link Collection} containing all matching instances of the given type in the database or an empty
|
||||
* collection if none are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Filter filter);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the specified depth, with Pagination.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param pagination The Pagination to be applied
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return A {@link Collection} containing all instances of the given type in the database or an empty collection if
|
||||
* none are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Pagination pagination, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the given class in the database hydrated to the default depth conforming to the
|
||||
* specified filter criteria.
|
||||
*
|
||||
* @param type The type of entity to return.
|
||||
* @param filter The filter to constrain entities with.
|
||||
* @param depth The depth to which the objects should be hydrated
|
||||
* @return A {@link Collection} containing all matching instances of the given type in the database or an empty
|
||||
* collection if none are found, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAll(Class<T> type, Filter filter, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains a property matching the given name with the given value.
|
||||
* This method assumes that the requested property/value combination will be unique for all entities of this type in
|
||||
* the database and will throw an exception unless exactly one result is found. If several entities are expected to be
|
||||
* returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @return The instance of T corresponding to the entity that matches the given property, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperty(Class<T> type, String propertyName, Object propertyValue);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains a property matching the given name with the given value.
|
||||
* This method assumes that the requested property/value combination will be unique for all entities of this type in
|
||||
* the database and will throw an exception unless exactly one result is found. If several entities are expected to be
|
||||
* returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return The instance of T corresponding to the entity that matches the given property, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperty(Class<T> type, String propertyName, Object propertyValue, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a property matching the given name with the given
|
||||
* value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @return A {@link Collection} containing all the entities that match the given property or an empty
|
||||
* {@link Collection} if there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperty(Class<T> type, String propertyName, Object propertyValue);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a property matching the given name with the given
|
||||
* value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return A {@link Collection} containing all the entities that match the given property or an empty
|
||||
* {@link Collection} if there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperty(Class<T> type, String propertyName, Object propertyValue, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains properties matching the ones supplied with given name and
|
||||
* value. This method assumes that the requested property/value combinations will be unique for all entities of this
|
||||
* type in the database and will throw an exception unless exactly one result is found. If several entities are
|
||||
* expected to be returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @return The instance of T corresponding to the entity that matches the given properties, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperties(Class<T> type, Filters parameters);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains properties matching the ones supplied with given name and
|
||||
* value. This method assumes that the requested property/value combinations will be unique for all entities of this
|
||||
* type in the database and will throw an exception unless exactly one result is found. If several entities are
|
||||
* expected to be returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return The instance of T corresponding to the entity that matches the given properties, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperties(Class<T> type, Filters parameters, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a properties matching the ones supplied with given
|
||||
* name and value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @return A {@link Collection} containing all the entities that match the given properties or an empty
|
||||
* {@link Collection} if there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperties(Class<T> type, Filters parameters);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a properties matching the ones supplied with given
|
||||
* name and value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related
|
||||
* entities. A value of 0 just loads the object's properties and no related entities. A value of -1 implies
|
||||
* no depth limit.
|
||||
* @return A {@link Collection} containing all the entities that match the given properties or an empty
|
||||
* {@link Collection} if there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperties(Class<T> type, Filters parameters, int depth);
|
||||
|
||||
/**
|
||||
* Saves the specified entity in the graph database. If the entity is currently transient then the persistent version
|
||||
* of the entity will be returned, containing its new graph ID.
|
||||
*
|
||||
* @param entity The entity to save
|
||||
* @return The saved entity
|
||||
*/
|
||||
<T> T save(T entity);
|
||||
|
||||
/**
|
||||
* Saves the specified entity in the graph database to a custom depth. If the entity is currently transient then the
|
||||
* persistent version of the entity will be returned, containing its new graph ID.
|
||||
*
|
||||
* @param entity The entity to save
|
||||
* @param depth The maximum number of relationships away from the entity to follow when saving related entities. A
|
||||
* value of 0 just saves the object's properties and no related entities. A value of -1 implies no depth
|
||||
* limit.
|
||||
* @return The saved entity
|
||||
*/
|
||||
<T> T save(T entity, int depth);
|
||||
|
||||
/**
|
||||
* Removes the given node or relationship entity from the graph. The entity is first removed from all indexes and then
|
||||
* deleted.
|
||||
*
|
||||
* @param entity The entity to delete
|
||||
*/
|
||||
void delete(Object entity);
|
||||
|
||||
/**
|
||||
* Removes all nodes or relationship entities of a specific type from the graph.
|
||||
*
|
||||
* @param type the type of entity to delete
|
||||
*/
|
||||
<T> void deleteAll(Class<T> type);
|
||||
|
||||
/**
|
||||
* Removes all mapping information from the current session
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Executes the specified Cypher query with the given parameters against the underlying Neo4j database and returns the
|
||||
* row-based result in the form of an {@link Iterable} of {@link Map}s.
|
||||
* <p>
|
||||
* Each of the resultant maps corresponds to a "row" in the result set and the key set in each map contains all the
|
||||
* names contained in the <code>RETURN</code> clause of the given query.
|
||||
* </p>
|
||||
*
|
||||
* @param cypherQuery The Cypher query to execute
|
||||
* @param params The parameter to merge into the cypher query or an empty {@link Map} if the given query isn't
|
||||
* parameterised
|
||||
* @return A {@link Query} containing an {@link Iterable} map representing query results and {@link QueryStatistics}
|
||||
* if applicable.
|
||||
* @throws RuntimeException if the given query is not a valid Cypherquery
|
||||
*/
|
||||
Result query(String cypherQuery, Map<String, ?> params);
|
||||
|
||||
/**
|
||||
* Runs the specified Cypher query with the given parameters against the underlying Neo4j database and returns the
|
||||
* result marshalled as an object of the requested type.
|
||||
*
|
||||
* @param entityType The {@link Class} denoting the type of entity to return
|
||||
* @param cypherQuery The Cypher query to execute
|
||||
* @param parameters The parameter to merge into the Cypher query or an empty {@link Map} if the query's not
|
||||
* parameterised
|
||||
* @return An instance of T that corresponds to the entity found by executing the query or <code>null</code> if
|
||||
* nothing is found by the query
|
||||
* @throws RuntimeException If more than one result is returned or there's an issue executing the query
|
||||
*/
|
||||
<T> T queryForObject(Class<T> entityType, String cypherQuery, Map<String, ?> parameters);
|
||||
|
||||
/**
|
||||
* Runs the specified Cypher query with the given parameters against the underlying Neo4j database and returns the
|
||||
* result marshalled as a group of objects of the requested type.
|
||||
*
|
||||
* @param entityType The {@link Class} denoting the type of entity to return
|
||||
* @param cypherQuery The Cypher query to execute
|
||||
* @param parameters The parameter to merge into the Cypher query or an empty {@link Map} if the query's not
|
||||
* parameterised
|
||||
* @return An {@link Iterable} over the entities found by executing the query or an empty <code>Iterable</code> if
|
||||
* nothing is found by the query, never <code>null</code>
|
||||
* @throws RuntimeException If there's an issue executing the query
|
||||
*/
|
||||
<T> Iterable<T> queryForObjects(Class<T> entityType, String cypherQuery, Map<String, ?> parameters);
|
||||
|
||||
/**
|
||||
* Given a cypher statement this method will return a {@link Query} object containing a collection of Map's which
|
||||
* represent Neo4j objects as properties, along with query statistics if applicable. Each element of the query result
|
||||
* is a map which you can access by the name of the returned field TODO: Are we going to use the neo4jOperations
|
||||
* conversion method to cast the value object to its proper class?
|
||||
*
|
||||
* @param cypher The parametrisable cypher to execute.
|
||||
* @param parameters Any parameters to attach to the cypher.
|
||||
* @param readOnly true if the query is readOnly, false otherwise
|
||||
* @return A {@link Query} of {@link Iterable}s with each entry representing a neo4j object's properties.
|
||||
*/
|
||||
Result query(String cypher, Map<String, ?> parameters, boolean readOnly);
|
||||
|
||||
/**
|
||||
* Provides the instance count for the given <em>node</em> entity type. This method is also provided by the
|
||||
* corresponding repository.
|
||||
*
|
||||
* @param entityClass The {@link Class} representing the type of node entity to count
|
||||
* @return The number of entities in the database of the given type
|
||||
*/
|
||||
long count(Class<?> entityClass);
|
||||
|
||||
// /**
|
||||
// * Issue a single Cypher update operation (such as a <tt>CREATE</tt>, <tt>MERGE</tt> or <tt>DELETE</tt> statement).
|
||||
// *
|
||||
// * @deprecated Use {@link Neo4jOperations}.query() to return both results as well as query statistics.
|
||||
// * @param cypherQuery The Cypher query to execute
|
||||
// * @return {@link QueryStatistics} representing statistics about graph modifications as a result of the cypher
|
||||
// execution.
|
||||
// */
|
||||
// @Deprecated
|
||||
// QueryStatistics execute(String cypherQuery);
|
||||
|
||||
// /**
|
||||
// * Allows a cypher statement with a modification statement to be executed.
|
||||
// *
|
||||
// * <p>Parameters may be scalars or domain objects themselves.</p>
|
||||
// * @deprecated Use {@link Neo4jOperations}.query() to return both results as well as query statistics.
|
||||
// * @param cypher The parametrisable cypher to execute.
|
||||
// * @param parameters Any parameters to attach to the cypher. These may be domain objects or scalars. Note that
|
||||
// * if a complex domain object is provided only the properties of that object will be set.
|
||||
// * If relationships of a provided object also need to be set then the cypher should reflect this
|
||||
// * and further domain object parameters provided.
|
||||
// *
|
||||
// * @return {@link QueryStatistics} representing statistics about graph modifications as a result of the cypher
|
||||
// execution.
|
||||
// */
|
||||
// @Deprecated
|
||||
// QueryStatistics execute(String cypher, Map<String, Object> parameters);
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.template;
|
||||
|
||||
|
||||
import static org.springframework.data.neo4j.util.IterableUtils.*;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -35,12 +34,12 @@ import org.springframework.data.neo4j.transaction.SessionFactoryUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Spring Data template for Neo4j, which is an implementation of {@link Neo4jOperations}. Indeed, framework users are encouraged
|
||||
* to favour coding against the {@link Neo4jOperations} interface rather than the {@link Neo4jTemplate} directly, as the
|
||||
* interface API will be more consistent over time and enhanced proxy objects of the interface may actually be created by Spring
|
||||
* for auto-wiring instead of this template.
|
||||
* Please note also that all methods on this class throw a {@link DataAccessException} if any underlying {@code Exception} is
|
||||
* thrown. Since {@link DataAccessException} is a runtime exception, this is not documented at the method level.
|
||||
* Spring Data template for Neo4j, which is an implementation of {@link Neo4jOperations}. Indeed, framework users are
|
||||
* encouraged to favour coding against the {@link Neo4jOperations} interface rather than the {@link Neo4jTemplate}
|
||||
* directly, as the interface API will be more consistent over time and enhanced proxy objects of the interface may
|
||||
* actually be created by Spring for auto-wiring instead of this template. Please note also that all methods on this
|
||||
* class throw a {@link DataAccessException} if any underlying {@code Exception} is thrown. Since
|
||||
* {@link DataAccessException} is a runtime exception, this is not documented at the method level.
|
||||
*
|
||||
* @author Adam George
|
||||
* @author Michal Bachman
|
||||
@@ -58,8 +57,7 @@ public class Neo4jTemplate implements Neo4jOperations, InitializingBean {
|
||||
/**
|
||||
* Create a new Neo4jTemplate instance.
|
||||
*/
|
||||
public Neo4jTemplate() {
|
||||
}
|
||||
public Neo4jTemplate() {}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Neo4jTemplate} based on the given Neo4j OGM {@link SessionFactory}.
|
||||
@@ -88,7 +86,6 @@ public class Neo4jTemplate implements Neo4jOperations, InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> T execute(Neo4jCallback<T> action) throws DataAccessException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
@@ -185,7 +182,8 @@ public class Neo4jTemplate implements Neo4jOperations, InitializingBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Collection<T> loadAll(final Class<T> type, final SortOrder sortOrder, final Pagination pagination, final int depth) {
|
||||
public <T> Collection<T> loadAll(final Class<T> type, final SortOrder sortOrder, final Pagination pagination,
|
||||
final int depth) {
|
||||
return execute(new Neo4jCallback<Collection<T>>() {
|
||||
@Override
|
||||
public Collection<T> doInNeo4jOgm(Session session) {
|
||||
@@ -214,7 +212,8 @@ public class Neo4jTemplate implements Neo4jOperations, InitializingBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Collection<T> loadAll(final Class<T> type, final Collection<Long> ids, final SortOrder sortOrder, final int depth) {
|
||||
public <T> Collection<T> loadAll(final Class<T> type, final Collection<Long> ids, final SortOrder sortOrder,
|
||||
final int depth) {
|
||||
return execute(new Neo4jCallback<Collection<T>>() {
|
||||
@Override
|
||||
public Collection<T> doInNeo4jOgm(Session session) {
|
||||
@@ -264,7 +263,8 @@ public class Neo4jTemplate implements Neo4jOperations, InitializingBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T loadByProperty(final Class<T> type, final String propertyName, final Object propertyValue, final int depth) {
|
||||
public <T> T loadByProperty(final Class<T> type, final String propertyName, final Object propertyValue,
|
||||
final int depth) {
|
||||
return execute(new Neo4jCallback<T>() {
|
||||
@Override
|
||||
public T doInNeo4jOgm(Session session) {
|
||||
@@ -312,7 +312,8 @@ public class Neo4jTemplate implements Neo4jOperations, InitializingBean {
|
||||
});
|
||||
}
|
||||
|
||||
public <T> Collection<T> loadAllByProperty(final Class<T> type, final String name, final Object value, final int depth) {
|
||||
public <T> Collection<T> loadAllByProperty(final Class<T> type, final String name, final Object value,
|
||||
final int depth) {
|
||||
return execute(new Neo4jCallback<Collection<T>>() {
|
||||
@Override
|
||||
public Collection<T> doInNeo4jOgm(Session session) {
|
||||
@@ -353,7 +354,6 @@ public class Neo4jTemplate implements Neo4jOperations, InitializingBean {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> T save(final T entity) {
|
||||
return execute(new Neo4jCallback<T>() {
|
||||
@@ -386,7 +386,8 @@ public class Neo4jTemplate implements Neo4jOperations, InitializingBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Iterable<T> queryForObjects(final Class<T> objectType, final String cypher, final Map<String, ?> parameters) {
|
||||
public <T> Iterable<T> queryForObjects(final Class<T> objectType, final String cypher,
|
||||
final Map<String, ?> parameters) {
|
||||
return execute(new Neo4jCallback<Iterable<T>>() {
|
||||
@Override
|
||||
public Iterable<T> doInNeo4jOgm(Session session) {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.transaction;
|
||||
|
||||
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
import org.neo4j.ogm.transaction.Transaction;
|
||||
@@ -34,30 +33,29 @@ import org.springframework.transaction.support.ResourceTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* {@link PlatformTransactionManager} implementation
|
||||
* for a single Neo4j OGM {@link SessionFactory}. Binds a Neo4j OGM
|
||||
* Session from the specified factory to the thread, potentially allowing for
|
||||
* one thread-bound Session per factory. {@link SharedSessionCreator}
|
||||
* is aware of thread-bound session and participates
|
||||
* in such transactions automatically. It is required for Neo4j OGM access code
|
||||
* supporting this transaction management mechanism.
|
||||
* <p>This transaction manager is appropriate for applications that use a single
|
||||
* Neo4j OGM SessionFactory for transactional data access. JTA (usually through
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager}) has not been tested
|
||||
* or considered at the moment.
|
||||
* <p>This transaction manager does not support nested transactions or
|
||||
* requires new propagation.
|
||||
* {@link PlatformTransactionManager} implementation for a single Neo4j OGM {@link SessionFactory}. Binds a Neo4j OGM
|
||||
* Session from the specified factory to the thread, potentially allowing for one thread-bound Session per factory.
|
||||
* {@link SharedSessionCreator} is aware of thread-bound session and participates in such transactions automatically. It
|
||||
* is required for Neo4j OGM access code supporting this transaction management mechanism.
|
||||
* <p>
|
||||
* This transaction manager is appropriate for applications that use a single Neo4j OGM SessionFactory for transactional
|
||||
* data access. JTA (usually through {@link org.springframework.transaction.jta.JtaTransactionManager}) has not been
|
||||
* tested or considered at the moment.
|
||||
* <p>
|
||||
* This transaction manager does not support nested transactions or requires new propagation.
|
||||
*
|
||||
* @author Mark Angrish
|
||||
* @see #setSessionFactory
|
||||
*/
|
||||
public class Neo4jTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
|
||||
public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
/**
|
||||
* Create a new Neo4jTransactionManager instance.
|
||||
* <p>An SessionFactory has to be set to be able to use it.
|
||||
* <p>
|
||||
* An SessionFactory has to be set to be able to use it.
|
||||
*
|
||||
* @see #setSessionFactory(SessionFactory)
|
||||
*/
|
||||
@@ -65,7 +63,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
setTransactionSynchronization(SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Neo4jTransactionManager instance.
|
||||
*
|
||||
@@ -76,17 +73,16 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the SessionFactory that this instance should manage transactions for.
|
||||
* <p>By default, a default SessionFactory will be retrieved by finding a
|
||||
* single unique bean of type SessionFactory in the containing BeanFactory.
|
||||
* <p>
|
||||
* By default, a default SessionFactory will be retrieved by finding a single unique bean of type SessionFactory in
|
||||
* the containing BeanFactory.
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the SessionFactory that this instance should manage transactions for.
|
||||
*/
|
||||
@@ -94,7 +90,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a default SessionFactory bean.
|
||||
*/
|
||||
@@ -105,7 +100,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (getSessionFactory() == null) {
|
||||
@@ -113,13 +107,11 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getResourceFactory() {
|
||||
return getSessionFactory();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() {
|
||||
Neo4jTransactionObject txObject = new Neo4jTransactionObject();
|
||||
@@ -127,28 +119,24 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
|
||||
if (sessionHolder != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found thread-bound Session [" + sessionHolder.getSession() +
|
||||
"] for Neo4j OGM transaction");
|
||||
logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Neo4j OGM transaction");
|
||||
}
|
||||
txObject.setSessionHolder(sessionHolder, false);
|
||||
}
|
||||
return txObject;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
return ((Neo4jTransactionObject) transaction).hasTransaction();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
|
||||
Neo4jTransactionObject txObject = (Neo4jTransactionObject) transaction;
|
||||
|
||||
try {
|
||||
if (txObject.getSessionHolder() == null ||
|
||||
txObject.getSessionHolder().isSynchronizedWithTransaction()) {
|
||||
if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
|
||||
Session session = sessionFactory.openSession();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Opened new Session [" + session + "] for Neo4j OGM transaction");
|
||||
@@ -165,12 +153,11 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
|
||||
if (definition.getPropagationBehavior() != TransactionDefinition.PROPAGATION_REQUIRED) {
|
||||
throw new IllegalTransactionStateException(
|
||||
"Neo4jTransactionManager only supports 'required' propagation.");
|
||||
throw new IllegalTransactionStateException("Neo4jTransactionManager only supports 'required' propagation.");
|
||||
}
|
||||
|
||||
Transaction transactionData;
|
||||
if (definition.isReadOnly() && txObject.isNewSessionHolder()) {
|
||||
if (definition.isReadOnly() && txObject.isNewSessionHolder()) {
|
||||
transactionData = session.beginTransaction(Transaction.Type.READ_ONLY);
|
||||
} else {
|
||||
transactionData = session.beginTransaction();
|
||||
@@ -200,10 +187,8 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the current transaction's Session.
|
||||
* Called after a transaction begin attempt failed.
|
||||
* Close the current transaction's Session. Called after a transaction begin attempt failed.
|
||||
*
|
||||
* @param txObject the current transaction
|
||||
*/
|
||||
@@ -222,17 +207,14 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Object doSuspend(Object transaction) {
|
||||
Neo4jTransactionObject txObject = (Neo4jTransactionObject) transaction;
|
||||
txObject.setSessionHolder(null, false);
|
||||
SessionHolder sessionHolder = (SessionHolder)
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
return new SuspendedResourcesHolder(sessionHolder);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doResume(Object transaction, Object suspendedResources) {
|
||||
SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources;
|
||||
@@ -241,11 +223,9 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
// -> can be safely removed, will be closed on transaction completion.
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
}
|
||||
TransactionSynchronizationManager.bindResource(
|
||||
getSessionFactory(), resourcesHolder.getSessionHolder());
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), resourcesHolder.getSessionHolder());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
|
||||
@@ -267,7 +247,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
Neo4jTransactionObject txObject = (Neo4jTransactionObject) status.getTransaction();
|
||||
@@ -293,18 +272,16 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
|
||||
Neo4jTransactionObject txObject = (Neo4jTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Setting Neo4j OGM transaction on Session [" +
|
||||
txObject.getSessionHolder().getSession() + "] rollback-only");
|
||||
logger.debug(
|
||||
"Setting Neo4j OGM transaction on Session [" + txObject.getSessionHolder().getSession() + "] rollback-only");
|
||||
}
|
||||
status.setRollbackOnly();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doCleanupAfterCompletion(Object transaction) {
|
||||
Neo4jTransactionObject txObject = (Neo4jTransactionObject) transaction;
|
||||
@@ -336,8 +313,7 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Neo4j OGM transaction object, representing a SessionHolder.
|
||||
* Used as transaction object by Neo4jTransactionManager.
|
||||
* Neo4j OGM transaction object, representing a SessionHolder. Used as transaction object by Neo4jTransactionManager.
|
||||
*/
|
||||
private static class Neo4jTransactionObject {
|
||||
|
||||
@@ -347,8 +323,7 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
|
||||
private Transaction transactionData;
|
||||
|
||||
void setSessionHolder(
|
||||
SessionHolder sessionHolder, boolean newSessionHolder) {
|
||||
void setSessionHolder(SessionHolder sessionHolder, boolean newSessionHolder) {
|
||||
this.sessionHolder = sessionHolder;
|
||||
this.newSessionHolder = newSessionHolder;
|
||||
}
|
||||
@@ -376,8 +351,7 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Holder for suspended resources.
|
||||
* Used internally by {@code doSuspend} and {@code doResume}.
|
||||
* Holder for suspended resources. Used internally by {@code doSuspend} and {@code doResume}.
|
||||
*/
|
||||
private static class SuspendedResourcesHolder {
|
||||
|
||||
|
||||
@@ -37,10 +37,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper class featuring methods for Neo4j OGM Session handling,
|
||||
* allowing for reuse of Session instances within transactions.
|
||||
* Also provides support for exception translation.
|
||||
* <p>Mainly intended for internal use within the framework.
|
||||
* Helper class featuring methods for Neo4j OGM Session handling, allowing for reuse of Session instances within
|
||||
* transactions. Also provides support for exception translation.
|
||||
* <p>
|
||||
* Mainly intended for internal use within the framework.
|
||||
*
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@@ -48,9 +48,7 @@ public class SessionFactoryUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SessionFactoryUtils.class);
|
||||
|
||||
|
||||
public static void closeSession(Session session) {
|
||||
}
|
||||
public static void closeSession(Session session) {}
|
||||
|
||||
public static Session getSession(SessionFactory sessionFactory) throws IllegalStateException {
|
||||
|
||||
@@ -58,11 +56,11 @@ public class SessionFactoryUtils {
|
||||
|
||||
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
|
||||
if (sessionHolder != null) {
|
||||
if (!sessionHolder.isSynchronizedWithTransaction() &&
|
||||
TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
if (!sessionHolder.isSynchronizedWithTransaction()
|
||||
&& TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
sessionHolder.setSynchronizedWithTransaction(true);
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
new SessionSynchronization(sessionHolder, sessionFactory, false));
|
||||
TransactionSynchronizationManager
|
||||
.registerSynchronization(new SessionSynchronization(sessionHolder, sessionFactory, false));
|
||||
}
|
||||
return sessionHolder.getSession();
|
||||
}
|
||||
@@ -83,22 +81,20 @@ public class SessionFactoryUtils {
|
||||
|
||||
sessionHolder = new SessionHolder(session);
|
||||
sessionHolder.setSynchronizedWithTransaction(true);
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
new SessionSynchronization(sessionHolder, sessionFactory, true));
|
||||
TransactionSynchronizationManager
|
||||
.registerSynchronization(new SessionSynchronization(sessionHolder, sessionFactory, true));
|
||||
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given runtime exception to an appropriate exception from the
|
||||
* {@code org.springframework.dao} hierarchy.
|
||||
* Return null if no translation is appropriate: any other exception may
|
||||
* have resulted from user code, and should not be translated.
|
||||
* Convert the given runtime exception to an appropriate exception from the {@code org.springframework.dao} hierarchy.
|
||||
* Return null if no translation is appropriate: any other exception may have resulted from user code, and should not
|
||||
* be translated.
|
||||
*
|
||||
* @param ex runtime exception that occurred
|
||||
* @return the corresponding DataAccessException instance,
|
||||
* or {@code null} if the exception should not be translated
|
||||
* @return the corresponding DataAccessException instance, or {@code null} if the exception should not be translated
|
||||
*/
|
||||
public static DataAccessException convertOgmAccessException(RuntimeException ex) {
|
||||
|
||||
@@ -161,9 +157,11 @@ public class SessionFactoryUtils {
|
||||
|
||||
if (dae != null) {
|
||||
try {
|
||||
final Constructor<? extends DataAccessException> constructor = dae.getDeclaredConstructor(String.class, Throwable.class);
|
||||
final Constructor<? extends DataAccessException> constructor = dae.getDeclaredConstructor(String.class,
|
||||
Throwable.class);
|
||||
return constructor.newInstance(ex.getMessage(), ex);
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException
|
||||
| InvocationTargetException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -176,15 +174,12 @@ public class SessionFactoryUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static class SessionSynchronization
|
||||
extends ResourceHolderSynchronization<SessionHolder, SessionFactory>
|
||||
private static class SessionSynchronization extends ResourceHolderSynchronization<SessionHolder, SessionFactory>
|
||||
implements Ordered {
|
||||
|
||||
private final boolean newSession;
|
||||
|
||||
SessionSynchronization(
|
||||
SessionHolder sessionHolder, SessionFactory sessionFactory, boolean newSession) {
|
||||
SessionSynchronization(SessionHolder sessionHolder, SessionFactory sessionFactory, boolean newSession) {
|
||||
super(sessionHolder, sessionFactory);
|
||||
this.newSession = newSession;
|
||||
}
|
||||
@@ -195,8 +190,7 @@ public class SessionFactoryUtils {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushResource(SessionHolder resourceHolder) {
|
||||
}
|
||||
public void flushResource(SessionHolder resourceHolder) {}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUnbindAtCompletion() {
|
||||
@@ -205,7 +199,7 @@ public class SessionFactoryUtils {
|
||||
|
||||
@Override
|
||||
protected boolean shouldReleaseAfterCompletion(SessionHolder resourceHolder) {
|
||||
// return !resourceHolder.getSession().isClosed();
|
||||
// return !resourceHolder.getSession().isClosed();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,10 @@ import org.springframework.transaction.support.ResourceHolderSupport;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Holder wrapping a Neo4j OGM Session.
|
||||
* Neo4jTransactionManager binds instances of this class to the thread,
|
||||
* for a given SessionFactory.
|
||||
*
|
||||
* <p>Note: This is an SPI class, not intended to be used by applications.
|
||||
* Holder wrapping a Neo4j OGM Session. Neo4jTransactionManager binds instances of this class to the thread, for a given
|
||||
* SessionFactory.
|
||||
* <p>
|
||||
* Note: This is an SPI class, not intended to be used by applications.
|
||||
*
|
||||
* @author Mark Angrish
|
||||
* @see Neo4jTransactionManager
|
||||
@@ -39,7 +38,6 @@ public class SessionHolder extends ResourceHolderSupport {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
|
||||
public Session getSession() {
|
||||
return this.session;
|
||||
}
|
||||
@@ -52,7 +50,6 @@ public class SessionHolder extends ResourceHolderSupport {
|
||||
return this.transactionActive;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
|
||||
@@ -30,12 +30,11 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Delegate for creating a shareable Neo4j OGM {@link Session}
|
||||
* reference for a given {@link SessionFactory}.
|
||||
* <p>A shared Session will behave just like a Session fetched from
|
||||
* an application SessionFactory.
|
||||
* It will delegate all calls to the current transactional Session, if any;
|
||||
* otherwise it will fall back to a newly created Session per operation.
|
||||
* Delegate for creating a shareable Neo4j OGM {@link Session} reference for a given {@link SessionFactory}.
|
||||
* <p>
|
||||
* A shared Session will behave just like a Session fetched from an application SessionFactory. It will delegate all
|
||||
* calls to the current transactional Session, if any; otherwise it will fall back to a newly created Session per
|
||||
* operation.
|
||||
*
|
||||
* @author Mark Angrish
|
||||
* @see Neo4jTransactionManager
|
||||
@@ -54,22 +53,18 @@ public class SharedSessionCreator {
|
||||
/**
|
||||
* Create a transactional Session proxy for the given SessionFactory.
|
||||
*
|
||||
* @param sessionFactory SessionFactory to obtain Sessions from as needed
|
||||
* {@code createSession} call (may be {@code null})
|
||||
* Session. Allows the addition or specification of proprietary interfaces.
|
||||
* @param sessionFactory SessionFactory to obtain Sessions from as needed {@code createSession} call (may be
|
||||
* {@code null}) Session. Allows the addition or specification of proprietary interfaces.
|
||||
* @return a shareable transactional Session proxy
|
||||
*/
|
||||
public static Session createSharedSession(SessionFactory sessionFactory) {
|
||||
|
||||
return (Session) Proxy.newProxyInstance(
|
||||
SharedSessionCreator.class.getClassLoader(),
|
||||
new Class<?>[]{Session.class}, new SharedSessionInvocationHandler(sessionFactory));
|
||||
return (Session) Proxy.newProxyInstance(SharedSessionCreator.class.getClassLoader(),
|
||||
new Class<?>[] { Session.class }, new SharedSessionInvocationHandler(sessionFactory));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invocation handler that delegates all calls to the current
|
||||
* transactional Session, if any; else, it will fall back
|
||||
* Invocation handler that delegates all calls to the current transactional Session, if any; else, it will fall back
|
||||
* to a newly created Session per operation.
|
||||
*/
|
||||
private static class SharedSessionInvocationHandler implements InvocationHandler {
|
||||
@@ -84,7 +79,6 @@ public class SharedSessionCreator {
|
||||
this.proxyClassLoader = this.targetFactory.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// Invocation on Session interface coming in...
|
||||
@@ -100,8 +94,7 @@ public class SharedSessionCreator {
|
||||
return "Shared Session proxy for target factory [" + targetFactory + "]";
|
||||
} else if (method.getName().equals("beginTransaction")) {
|
||||
throw new IllegalStateException(
|
||||
"Not allowed to create transaction on shared Session - " +
|
||||
"use Spring transactions instead");
|
||||
"Not allowed to create transaction on shared Session - " + "use Spring transactions instead");
|
||||
}
|
||||
|
||||
// Determine current Session: either the transactional one
|
||||
@@ -109,11 +102,11 @@ public class SharedSessionCreator {
|
||||
Session target = SessionFactoryUtils.getSession(this.targetFactory);
|
||||
|
||||
if (transactionRequiringMethods.contains(method.getName())) {
|
||||
if (target == null || (!TransactionSynchronizationManager.isActualTransactionActive()
|
||||
&& target.getTransaction() != null
|
||||
&& EnumSet.of(CLOSED, COMMITTED, ROLLEDBACK).contains(target.getTransaction().status()))) {
|
||||
throw new IllegalStateException("No Session with actual transaction available " +
|
||||
"for current thread - cannot reliably process '" + method.getName() + "' call");
|
||||
if (target == null
|
||||
|| (!TransactionSynchronizationManager.isActualTransactionActive() && target.getTransaction() != null
|
||||
&& EnumSet.of(CLOSED, COMMITTED, ROLLEDBACK).contains(target.getTransaction().status()))) {
|
||||
throw new IllegalStateException("No Session with actual transaction available "
|
||||
+ "for current thread - cannot reliably process '" + method.getName() + "' call");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
|
||||
package org.springframework.data.neo4j.util;
|
||||
|
||||
import org.neo4j.ogm.exception.NotFoundException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.neo4j.ogm.exception.NotFoundException;
|
||||
|
||||
/**
|
||||
* Utility methods for dealing with {@link Iterable}s.
|
||||
*
|
||||
@@ -27,229 +27,228 @@ import java.util.List;
|
||||
*/
|
||||
public final class IterableUtils {
|
||||
|
||||
/**
|
||||
* Count items in an iterable.
|
||||
*
|
||||
* @param iterable to count items in.
|
||||
* @return number of items in the iterable.
|
||||
*/
|
||||
public static long count(Iterable iterable) {
|
||||
if (iterable instanceof Collection) {
|
||||
return ((Collection) iterable).size();
|
||||
}
|
||||
/**
|
||||
* Count items in an iterable.
|
||||
*
|
||||
* @param iterable to count items in.
|
||||
* @return number of items in the iterable.
|
||||
*/
|
||||
public static long count(Iterable iterable) {
|
||||
if (iterable instanceof Collection) {
|
||||
return ((Collection) iterable).size();
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (Object o : iterable) {
|
||||
count++;
|
||||
}
|
||||
int count = 0;
|
||||
for (Object o : iterable) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an iterable contains the given object.
|
||||
*
|
||||
* @param iterable to check in.
|
||||
* @param object to look for.
|
||||
* @param <T> type of the objects stored in the iterable.
|
||||
* @return true iff the object is contained in the iterable.
|
||||
*/
|
||||
public static <T> boolean contains(Iterable<T> iterable, T object) {
|
||||
if (iterable instanceof Collection) {
|
||||
return ((Collection) iterable).contains(object);
|
||||
}
|
||||
/**
|
||||
* Check whether an iterable contains the given object.
|
||||
*
|
||||
* @param iterable to check in.
|
||||
* @param object to look for.
|
||||
* @param <T> type of the objects stored in the iterable.
|
||||
* @return true iff the object is contained in the iterable.
|
||||
*/
|
||||
public static <T> boolean contains(Iterable<T> iterable, T object) {
|
||||
if (iterable instanceof Collection) {
|
||||
return ((Collection) iterable).contains(object);
|
||||
}
|
||||
|
||||
for (T t : iterable) {
|
||||
if (t.equals(object)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (T t : iterable) {
|
||||
if (t.equals(object)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an iterable to a list.
|
||||
*
|
||||
* @param iterable to convert.
|
||||
* @param <T> type of the items held.
|
||||
* @return a list.
|
||||
*/
|
||||
public static <T> List<T> toList(Iterable<T> iterable) {
|
||||
List<T> list = new ArrayList<>();
|
||||
/**
|
||||
* Convert an iterable to a list.
|
||||
*
|
||||
* @param iterable to convert.
|
||||
* @param <T> type of the items held.
|
||||
* @return a list.
|
||||
*/
|
||||
public static <T> List<T> toList(Iterable<T> iterable) {
|
||||
List<T> list = new ArrayList<>();
|
||||
|
||||
if (iterable instanceof Collection) {
|
||||
list.addAll((Collection<T>) iterable);
|
||||
} else {
|
||||
for (T next : iterable) {
|
||||
list.add(next);
|
||||
}
|
||||
}
|
||||
if (iterable instanceof Collection) {
|
||||
list.addAll((Collection<T>) iterable);
|
||||
} else {
|
||||
for (T next : iterable) {
|
||||
list.add(next);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single element from iterator.
|
||||
*
|
||||
* @param iterator to find a single element.
|
||||
* @param notFoundMessage exception message if there are no elements.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingle(Iterator<T> iterator, String notFoundMessage) {
|
||||
T result = getSingleOrNull(iterator);
|
||||
/**
|
||||
* Get a single element from iterator.
|
||||
*
|
||||
* @param iterator to find a single element.
|
||||
* @param notFoundMessage exception message if there are no elements.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingle(Iterator<T> iterator, String notFoundMessage) {
|
||||
T result = getSingleOrNull(iterator);
|
||||
|
||||
if (result == null) {
|
||||
throw new NotFoundException(notFoundMessage);
|
||||
}
|
||||
if (result == null) {
|
||||
throw new NotFoundException(notFoundMessage);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single element from iterable.
|
||||
*
|
||||
* @param iterable to find a single element.
|
||||
* @param notFoundMessage exception message if there are no elements.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingle(Iterable<T> iterable, String notFoundMessage) {
|
||||
return getSingle(iterable.iterator(), notFoundMessage);
|
||||
}
|
||||
/**
|
||||
* Get a single element from iterable.
|
||||
*
|
||||
* @param iterable to find a single element.
|
||||
* @param notFoundMessage exception message if there are no elements.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingle(Iterable<T> iterable, String notFoundMessage) {
|
||||
return getSingle(iterable.iterator(), notFoundMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single element from iterator.
|
||||
*
|
||||
* @param iterator to find a single element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingle(Iterator<T> iterator) {
|
||||
return getSingle(iterator, "Iterator is empty");
|
||||
}
|
||||
/**
|
||||
* Get a single element from iterator.
|
||||
*
|
||||
* @param iterator to find a single element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingle(Iterator<T> iterator) {
|
||||
return getSingle(iterator, "Iterator is empty");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single element from iterable.
|
||||
*
|
||||
* @param iterable to find a single element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingle(Iterable<T> iterable) {
|
||||
return getSingle(iterable.iterator(), "Iterable is empty");
|
||||
}
|
||||
/**
|
||||
* Get a single element from iterable.
|
||||
*
|
||||
* @param iterable to find a single element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingle(Iterable<T> iterable) {
|
||||
return getSingle(iterable.iterator(), "Iterable is empty");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single element from iterator.
|
||||
*
|
||||
* @param iterator to find a single element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one, null iff there is 0.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingleOrNull(Iterator<T> iterator) {
|
||||
T result = null;
|
||||
/**
|
||||
* Get a single element from iterator.
|
||||
*
|
||||
* @param iterator to find a single element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one, null iff there is 0.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingleOrNull(Iterator<T> iterator) {
|
||||
T result = null;
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
result = iterator.next();
|
||||
}
|
||||
if (iterator.hasNext()) {
|
||||
result = iterator.next();
|
||||
}
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
throw new IllegalStateException("Iterable has more than one element, which is unexpected");
|
||||
}
|
||||
if (iterator.hasNext()) {
|
||||
throw new IllegalStateException("Iterable has more than one element, which is unexpected");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single element from iterable.
|
||||
*
|
||||
* @param iterable to find a single element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one, null iff there is 0.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingleOrNull(Iterable<T> iterable) {
|
||||
return getSingleOrNull(iterable.iterator());
|
||||
}
|
||||
/**
|
||||
* Get a single element from iterable.
|
||||
*
|
||||
* @param iterable to find a single element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is exactly one, null iff there is 0.
|
||||
* @throws IllegalStateException in case the iterable contains more than 1 element.
|
||||
*/
|
||||
public static <T> T getSingleOrNull(Iterable<T> iterable) {
|
||||
return getSingleOrNull(iterable.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first element from iterator.
|
||||
*
|
||||
* @param iterator to find the first element.
|
||||
* @param notFoundMessage exception message if there are no elements.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is one or more.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
*/
|
||||
public static <T> T getFirst(Iterator<T> iterator, String notFoundMessage) {
|
||||
T result = null;
|
||||
/**
|
||||
* Get the first element from iterator.
|
||||
*
|
||||
* @param iterator to find the first element.
|
||||
* @param notFoundMessage exception message if there are no elements.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is one or more.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
*/
|
||||
public static <T> T getFirst(Iterator<T> iterator, String notFoundMessage) {
|
||||
T result = null;
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
result = iterator.next();
|
||||
}
|
||||
if (iterator.hasNext()) {
|
||||
result = iterator.next();
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
throw new NotFoundException(notFoundMessage);
|
||||
}
|
||||
if (result == null) {
|
||||
throw new NotFoundException(notFoundMessage);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first element from iterable.
|
||||
*
|
||||
* @param iterable to find the first element.
|
||||
* @param notFoundMessage exception message if there are no elements.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is one or more.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
*/
|
||||
public static <T> T getFirst(Iterable<T> iterable, String notFoundMessage) {
|
||||
return getFirst(iterable.iterator(), notFoundMessage);
|
||||
}
|
||||
/**
|
||||
* Get the first element from iterable.
|
||||
*
|
||||
* @param iterable to find the first element.
|
||||
* @param notFoundMessage exception message if there are no elements.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is one or more.
|
||||
* @throws NotFoundException in case there are no elements.
|
||||
*/
|
||||
public static <T> T getFirst(Iterable<T> iterable, String notFoundMessage) {
|
||||
return getFirst(iterable.iterator(), notFoundMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first element from iterator.
|
||||
*
|
||||
* @param iterator to find the first element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is one or more, null if there is none.
|
||||
*/
|
||||
public static <T> T getFirstOrNull(Iterator<T> iterator) {
|
||||
T result = null;
|
||||
/**
|
||||
* Get the first element from iterator.
|
||||
*
|
||||
* @param iterator to find the first element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is one or more, null if there is none.
|
||||
*/
|
||||
public static <T> T getFirstOrNull(Iterator<T> iterator) {
|
||||
T result = null;
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
result = iterator.next();
|
||||
}
|
||||
if (iterator.hasNext()) {
|
||||
result = iterator.next();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first element from iterable.
|
||||
*
|
||||
* @param iterable to find the first element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is one or more, null if there is none.
|
||||
*/
|
||||
public static <T> T getFirstOrNull(Iterable<T> iterable) {
|
||||
return getFirstOrNull(iterable.iterator());
|
||||
}
|
||||
/**
|
||||
* Get the first element from iterable.
|
||||
*
|
||||
* @param iterable to find the first element.
|
||||
* @param <T> type of the element.
|
||||
* @return the element iff there is one or more, null if there is none.
|
||||
*/
|
||||
public static <T> T getFirstOrNull(Iterable<T> iterable) {
|
||||
return getFirstOrNull(iterable.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* private constructor to prevent instantiation.
|
||||
*/
|
||||
private IterableUtils() {
|
||||
}
|
||||
/**
|
||||
* private constructor to prevent instantiation.
|
||||
*/
|
||||
private IterableUtils() {}
|
||||
}
|
||||
|
||||
@@ -26,15 +26,14 @@ import org.springframework.web.context.request.async.DeferredResult;
|
||||
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
|
||||
|
||||
/**
|
||||
* An interceptor with asynchronous web requests used in OpenSessionInViewFilter and
|
||||
* OpenSessionInViewInterceptor.
|
||||
* Ensures the following:
|
||||
* 1) The session is bound/unbound when "callable processing" is started
|
||||
* 2) The session is closed if an async request times out
|
||||
* An interceptor with asynchronous web requests used in OpenSessionInViewFilter and OpenSessionInViewInterceptor.
|
||||
* Ensures the following: 1) The session is bound/unbound when "callable processing" is started 2) The session is closed
|
||||
* if an async request times out
|
||||
*
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter implements DeferredResultProcessingInterceptor {
|
||||
class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter
|
||||
implements DeferredResultProcessingInterceptor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AsyncRequestInterceptor.class);
|
||||
|
||||
@@ -49,7 +48,6 @@ class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter imple
|
||||
this.sessionHolder = sessionHolder;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
|
||||
bindSession();
|
||||
@@ -68,7 +66,7 @@ class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter imple
|
||||
@Override
|
||||
public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) {
|
||||
this.timeoutInProgress = true;
|
||||
return RESULT_NONE; // give other interceptors a chance to handle the timeout
|
||||
return RESULT_NONE; // give other interceptors a chance to handle the timeout
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,13 +78,12 @@ class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter imple
|
||||
if (this.timeoutInProgress) {
|
||||
logger.debug("Closing Neo4j OGM Session after async request timeout");
|
||||
// close session.
|
||||
// SessionFactoryUtils.closeSession(session);
|
||||
// SessionFactoryUtils.closeSession(session);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
}
|
||||
public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {}
|
||||
|
||||
@Override
|
||||
public <T> void preProcess(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
@@ -101,11 +98,12 @@ class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter imple
|
||||
@Override
|
||||
public <T> boolean handleTimeout(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
this.timeoutInProgress = true;
|
||||
return true; // give other interceptors a chance to handle the timeout
|
||||
return true; // give other interceptors a chance to handle the timeout
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void afterCompletion(NativeWebRequest nativeWebRequest, DeferredResult<T> deferredResult) throws Exception {
|
||||
public <T> void afterCompletion(NativeWebRequest nativeWebRequest, DeferredResult<T> deferredResult)
|
||||
throws Exception {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,16 +13,16 @@
|
||||
|
||||
package org.springframework.data.neo4j.web.support;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
|
||||
import org.springframework.data.neo4j.transaction.SessionFactoryUtils;
|
||||
import org.springframework.data.neo4j.transaction.SessionHolder;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -33,16 +33,15 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Servlet Filter that binds a Neo4j OGM Session to the thread for the
|
||||
* entire processing of the request. Intended for the "Open Session in
|
||||
* View" pattern, i.e. to allow for lazy loading in web views despite the
|
||||
* original transactions already being completed.
|
||||
* <p>This filter makes OGM Sessions available via the current thread,
|
||||
* which will be autodetected by transaction managers. At the moment this service is
|
||||
* only suitable for transactions via {@link Neo4jTransactionManager}.
|
||||
* <p>Looks up the SessionFactory in Spring's root web application context.
|
||||
* Supports an "sessionFactoryBeanName" filter init-param in {@code web.xml};
|
||||
* the default bean name is "sessionFactory".
|
||||
* Servlet Filter that binds a Neo4j OGM Session to the thread for the entire processing of the request. Intended for
|
||||
* the "Open Session in View" pattern, i.e. to allow for lazy loading in web views despite the original transactions
|
||||
* already being completed.
|
||||
* <p>
|
||||
* This filter makes OGM Sessions available via the current thread, which will be autodetected by transaction managers.
|
||||
* At the moment this service is only suitable for transactions via {@link Neo4jTransactionManager}.
|
||||
* <p>
|
||||
* Looks up the SessionFactory in Spring's root web application context. Supports an "sessionFactoryBeanName" filter
|
||||
* init-param in {@code web.xml}; the default bean name is "sessionFactory".
|
||||
*
|
||||
* @author Mark Angrish
|
||||
* @see OpenSessionInViewInterceptor
|
||||
@@ -63,9 +62,9 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
||||
private volatile SessionFactory sessionFactory;
|
||||
|
||||
/**
|
||||
* Set the bean name of the SessionFactory to fetch from Spring's
|
||||
* root application context.
|
||||
* <p>Default is "sessionFactory".
|
||||
* Set the bean name of the SessionFactory to fetch from Spring's root application context.
|
||||
* <p>
|
||||
* Default is "sessionFactory".
|
||||
*
|
||||
* @see #DEFAULT_SESSION_FACTORY_BEAN_NAME
|
||||
*/
|
||||
@@ -74,38 +73,31 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean name of the SessionFactory to fetch from Spring's
|
||||
* root application context.
|
||||
* Return the bean name of the SessionFactory to fetch from Spring's root application context.
|
||||
*/
|
||||
protected String getSessionFactoryBeanName() {
|
||||
return this.sessionFactoryBeanName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns "false" so that the filter may re-bind the opened {@code Session}
|
||||
* to each asynchronously dispatched thread and postpone closing it until the very
|
||||
* last asynchronous dispatch.
|
||||
* Returns "false" so that the filter may re-bind the opened {@code Session} to each asynchronously dispatched thread
|
||||
* and postpone closing it until the very last asynchronous dispatch.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldNotFilterAsyncDispatch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns "false" so that the filter may provide an {@code Session}
|
||||
* to each error dispatches.
|
||||
* Returns "false" so that the filter may provide an {@code Session} to each error dispatches.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldNotFilterErrorDispatch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
SessionFactory sessionFactory = lookupSessionFactory(request);
|
||||
@@ -139,17 +131,17 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
||||
if (!isAsyncStarted(request)) {
|
||||
logger.debug("Closed Neo4J OGM Session in OpenSessionInViewFilter");
|
||||
// close session.
|
||||
// SessionFactoryUtils.closeSession(session);
|
||||
// SessionFactoryUtils.closeSession(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the SessionFactory that this filter should use,
|
||||
* taking the current HTTP request as argument.
|
||||
* <p>The default implementation delegates to the {@code lookupSessionFactory}
|
||||
* without arguments, caching the SessionFactory reference once obtained.
|
||||
* Look up the SessionFactory that this filter should use, taking the current HTTP request as argument.
|
||||
* <p>
|
||||
* The default implementation delegates to the {@code lookupSessionFactory} without arguments, caching the
|
||||
* SessionFactory reference once obtained.
|
||||
*
|
||||
* @return the SessionFactory to use
|
||||
* @see #lookupSessionFactory()
|
||||
@@ -163,8 +155,8 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
||||
|
||||
/**
|
||||
* Look up the SessionFactory that this filter should use.
|
||||
* <p>The default implementation looks for a bean with the specified name
|
||||
* in Spring's root application context.
|
||||
* <p>
|
||||
* The default implementation looks for a bean with the specified name in Spring's root application context.
|
||||
*
|
||||
* @return the SessionFactory to use
|
||||
* @see #getSessionFactoryBeanName
|
||||
@@ -182,10 +174,10 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Neo4j OGM Session to be bound to a request.
|
||||
* <p>Can be overridden in subclasses.
|
||||
* <p>
|
||||
* Can be overridden in subclasses.
|
||||
*
|
||||
* @param sessionFactory the SessionFactory to use
|
||||
* @see SessionFactory#openSession
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.web.support;
|
||||
|
||||
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
import org.slf4j.Logger;
|
||||
@@ -32,15 +31,15 @@ import org.springframework.web.context.request.async.WebAsyncManager;
|
||||
import org.springframework.web.context.request.async.WebAsyncUtils;
|
||||
|
||||
/**
|
||||
* Spring web request interceptor that binds a Neo4j OGM Session to the
|
||||
* thread for the entire processing of the request. Intended for the "Open
|
||||
* Session in View" pattern, i.e. to allow for lazy loading in
|
||||
* web views despite the original transactions already being completed.
|
||||
* <p>This interceptor makes Neo4j OGM Sessions available via the current thread,
|
||||
* which will be autodetected by transaction managers. It is suitable for service
|
||||
* layer transactions via {@link Neo4jTransactionManager}.
|
||||
* <p>In contrast to {@link OpenSessionInViewFilter}, this interceptor is set
|
||||
* up in a Spring application context and can thus take advantage of bean wiring.
|
||||
* Spring web request interceptor that binds a Neo4j OGM Session to the thread for the entire processing of the request.
|
||||
* Intended for the "Open Session in View" pattern, i.e. to allow for lazy loading in web views despite the original
|
||||
* transactions already being completed.
|
||||
* <p>
|
||||
* This interceptor makes Neo4j OGM Sessions available via the current thread, which will be autodetected by transaction
|
||||
* managers. It is suitable for service layer transactions via {@link Neo4jTransactionManager}.
|
||||
* <p>
|
||||
* In contrast to {@link OpenSessionInViewFilter}, this interceptor is set up in a Spring application context and can
|
||||
* thus take advantage of bean wiring.
|
||||
*
|
||||
* @author Mark Angrish
|
||||
* @see OpenSessionInViewFilter
|
||||
@@ -55,8 +54,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
|
||||
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/**
|
||||
* Suffix that gets appended to the SessionFactory toString
|
||||
* representation for the "participate in existing session
|
||||
* Suffix that gets appended to the SessionFactory toString representation for the "participate in existing session
|
||||
* handling" request attribute.
|
||||
*
|
||||
* @see #getParticipateAttributeName
|
||||
@@ -66,8 +64,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
/**
|
||||
* Set the Neo4j OGM SessionFactory that should be used to create
|
||||
* Sessions.
|
||||
* Set the Neo4j OGM SessionFactory that should be used to create Sessions.
|
||||
*
|
||||
* @see SessionFactory#openSession
|
||||
*/
|
||||
@@ -76,8 +73,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Neo4j OGM SessionFactory that should be used to create
|
||||
* Sessions.
|
||||
* Return the Neo4j OGM SessionFactory that should be used to create Sessions.
|
||||
*/
|
||||
public SessionFactory getSessionFactory() {
|
||||
return this.sessionFactory;
|
||||
@@ -93,7 +89,6 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void preHandle(WebRequest request) throws DataAccessException {
|
||||
String participateAttributeName = getParticipateAttributeName();
|
||||
@@ -123,8 +118,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(WebRequest request, ModelMap model) {
|
||||
}
|
||||
public void postHandle(WebRequest request, ModelMap model) {}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException {
|
||||
@@ -132,7 +126,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
logger.debug("Closed Neo4j OGM Session in OpenSessionInViewInterceptor");
|
||||
// close session.
|
||||
// SessionFactoryUtils.closeSession(session);
|
||||
// SessionFactoryUtils.closeSession(session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,9 +153,8 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the request attribute that identifies that a request is
|
||||
* already filtered. Default implementation takes the toString representation
|
||||
* of the SessionFactory instance and appends ".FILTERED".
|
||||
* Return the name of the request attribute that identifies that a request is already filtered. Default implementation
|
||||
* takes the toString representation of the SessionFactory instance and appends ".FILTERED".
|
||||
*
|
||||
* @see #PARTICIPATE_SUFFIX
|
||||
*/
|
||||
@@ -169,7 +162,6 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
|
||||
return getSessionFactory().toString() + PARTICIPATE_SUFFIX;
|
||||
}
|
||||
|
||||
|
||||
private boolean applyCallableInterceptor(WebAsyncManager asyncManager, String key) {
|
||||
if (asyncManager.getCallableInterceptor(key) == null) {
|
||||
return false;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.domain.sample;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
@@ -28,8 +27,7 @@ public class Role {
|
||||
|
||||
private static final String PREFIX = "ROLE_";
|
||||
|
||||
@GraphId
|
||||
private Long id;
|
||||
@GraphId private Long id;
|
||||
|
||||
private UUID uuid;
|
||||
private String name;
|
||||
|
||||
@@ -23,8 +23,7 @@ import org.springframework.util.Assert;
|
||||
@NodeEntity
|
||||
public class SampleEntity {
|
||||
|
||||
@GraphId
|
||||
protected Long id;
|
||||
@GraphId protected Long id;
|
||||
private String first;
|
||||
private String second;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
import org.neo4j.ogm.annotation.typeconversion.DateString;
|
||||
|
||||
|
||||
/**
|
||||
* Domain class representing a person emphasizing the use of {@code AbstractEntity}. No declaration of an id is
|
||||
* required. The id is typed by the parameterizable superclass.
|
||||
@@ -18,8 +17,7 @@ import org.neo4j.ogm.annotation.typeconversion.DateString;
|
||||
@NodeEntity
|
||||
public class User {
|
||||
|
||||
@GraphId
|
||||
private Long id;
|
||||
@GraphId private Long id;
|
||||
|
||||
private String firstname;
|
||||
|
||||
@@ -33,11 +31,9 @@ public class User {
|
||||
|
||||
private String emailAddress;
|
||||
|
||||
@Relationship
|
||||
private Set<User> colleagues;
|
||||
@Relationship private Set<User> colleagues;
|
||||
|
||||
@Relationship
|
||||
private Set<Role> roles;
|
||||
@Relationship private Set<Role> roles;
|
||||
|
||||
private User manager;
|
||||
|
||||
@@ -47,8 +43,7 @@ public class User {
|
||||
|
||||
private Set<String> attributes;
|
||||
|
||||
@DateString
|
||||
private Date dateOfBirth;
|
||||
@DateString private Date dateOfBirth;
|
||||
|
||||
/**
|
||||
* Creates a new empty instance of {@code User}.
|
||||
|
||||
@@ -12,8 +12,7 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class EventPublisher extends EventListenerAdapter {
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher publisher;
|
||||
@Autowired private ApplicationEventPublisher publisher;
|
||||
|
||||
@Override
|
||||
public void onPreSave(Event event) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.springframework.data.neo4j.events;
|
||||
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -21,7 +20,7 @@ public class Neo4jModificationEventListener {
|
||||
|
||||
@EventListener
|
||||
public void onPreSaveEvent(PreSaveEvent event) {
|
||||
preSaveEvent= event;
|
||||
preSaveEvent = event;
|
||||
preSaveEventCount++;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.neo4j.ogm.session.event.Event;
|
||||
*/
|
||||
public class PostDeleteEvent extends ModificationEvent {
|
||||
|
||||
public PostDeleteEvent( Event event) {
|
||||
public PostDeleteEvent(Event event) {
|
||||
super(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.neo4j.ogm.session.event.Event;
|
||||
*/
|
||||
public class PreDeleteEvent extends ModificationEvent {
|
||||
|
||||
public PreDeleteEvent( Event event) {
|
||||
public PreDeleteEvent(Event event) {
|
||||
super(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
* @author Luanne Misquitta
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@ContextConfiguration(classes = {FriendContext.class})
|
||||
@ContextConfiguration(classes = { FriendContext.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class FriendIT extends MultiDriverTestClass {
|
||||
|
||||
@@ -47,11 +47,10 @@ public class FriendIT extends MultiDriverTestClass {
|
||||
@Autowired FriendService friendService;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass(){
|
||||
public static void beforeClass() {
|
||||
graphDatabaseService = getGraphDatabaseService();
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void cleanUpDatabase() {
|
||||
graphDatabaseService.execute("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE r, n");
|
||||
|
||||
@@ -27,8 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Service
|
||||
public class FriendService {
|
||||
|
||||
@Autowired
|
||||
Session session;
|
||||
@Autowired Session session;
|
||||
|
||||
@Transactional
|
||||
public void createPersonAndFriends() {
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.friends.domain;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Luanne Misquitta
|
||||
*/
|
||||
@@ -30,8 +30,7 @@ public class Person {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
@Relationship(type = "IS_FRIEND")
|
||||
private Set<Friendship> friendships = new HashSet<>();
|
||||
@Relationship(type = "IS_FRIEND") private Set<Friendship> friendships = new HashSet<>();
|
||||
|
||||
public Person() {}
|
||||
|
||||
|
||||
@@ -40,17 +40,15 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* @author Vince Bickers
|
||||
*/
|
||||
@ContextConfiguration(classes = {GalaxyContext.class})
|
||||
@ContextConfiguration(classes = { GalaxyContext.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@Transactional
|
||||
public class GalaxyServiceIT extends MultiDriverTestClass {
|
||||
|
||||
@Autowired
|
||||
private GalaxyService galaxyService;
|
||||
@Autowired private GalaxyService galaxyService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -98,7 +96,6 @@ public class GalaxyServiceIT extends MultiDriverTestClass {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldFindWorldsByName() {
|
||||
galaxyService.makeSomeWorlds();
|
||||
@@ -140,9 +137,7 @@ public class GalaxyServiceIT extends MultiDriverTestClass {
|
||||
galaxyService.makeSomeWorlds();
|
||||
|
||||
for (World worldWithOneMoon : galaxyService.findAllByNumberOfMoons(1)) {
|
||||
assertThat(
|
||||
worldWithOneMoon.getName(),
|
||||
is(anyOf(containsString("Earth"), containsString("Midgard"))));
|
||||
assertThat(worldWithOneMoon.getName(), is(anyOf(containsString("Earth"), containsString("Midgard"))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,11 +213,11 @@ public class GalaxyServiceIT extends MultiDriverTestClass {
|
||||
sum += world.getId();
|
||||
}
|
||||
// note: this doesn't work, because deleted node ids are not reclaimed
|
||||
// long sum = (size * size - size) / 2; // 0-based node ids
|
||||
// long sum = (size * size - size) / 2; // 0-based node ids
|
||||
|
||||
Pageable pageable = new PageRequest(0, 3);
|
||||
|
||||
for (; ; ) {
|
||||
for (;;) {
|
||||
Page<World> page = galaxyService.findAllWorlds(pageable);
|
||||
for (World world : page) {
|
||||
System.out.println(world.getName() + ":" + world.getId());
|
||||
@@ -249,7 +244,7 @@ public class GalaxyServiceIT extends MultiDriverTestClass {
|
||||
Pageable pageable = new PageRequest(0, 3, Sort.Direction.ASC, "name");
|
||||
|
||||
int i = 0;
|
||||
for (; ; ) {
|
||||
for (;;) {
|
||||
Page<World> page = galaxyService.findAllWorlds(pageable);
|
||||
for (World world : page) {
|
||||
assertEquals(sortedNames[i], world.getName());
|
||||
@@ -306,7 +301,7 @@ public class GalaxyServiceIT extends MultiDriverTestClass {
|
||||
names.add(world.getName());
|
||||
}
|
||||
|
||||
String[] sortedNames = names.toArray(new String[]{});
|
||||
String[] sortedNames = names.toArray(new String[] {});
|
||||
Arrays.sort(sortedNames);
|
||||
return sortedNames;
|
||||
}
|
||||
|
||||
@@ -28,34 +28,31 @@ import org.springframework.data.neo4j.examples.galaxy.domain.World;
|
||||
import org.springframework.data.neo4j.examples.galaxy.repo.WorldRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
@ContextConfiguration(classes = {GalaxyContext.class})
|
||||
@ContextConfiguration(classes = { GalaxyContext.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class WorldRepositoryIT extends MultiDriverTestClass {
|
||||
|
||||
@Autowired
|
||||
WorldRepository worldRepository;
|
||||
@Autowired WorldRepository worldRepository;
|
||||
|
||||
@Autowired
|
||||
TransactionTemplate transactionTemplate;
|
||||
@Autowired TransactionTemplate transactionTemplate;
|
||||
|
||||
boolean failed = false;
|
||||
|
||||
/**
|
||||
* see https://jira.spring.io/browse/DATAGRAPH-951
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void multipleThreadsResultsGetMixedUp() throws Exception {
|
||||
|
||||
World world1 = new World("world 1", 1);
|
||||
worldRepository.save(world1, 0);
|
||||
World world1 = new World("world 1", 1);
|
||||
worldRepository.save(world1, 0);
|
||||
|
||||
World world2 = new World("world 2", 2);
|
||||
worldRepository.save(world2, 0);
|
||||
World world2 = new World("world 2", 2);
|
||||
worldRepository.save(world2, 0);
|
||||
|
||||
int iterations = 10;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.transaction.support.TransactionTemplate;
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan({"org.springframework.data.neo4j.examples.galaxy.service"})
|
||||
@ComponentScan({ "org.springframework.data.neo4j.examples.galaxy.service" })
|
||||
@PropertySource("classpath:helloworld.properties")
|
||||
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.galaxy.repo")
|
||||
@EnableTransactionManagement
|
||||
@@ -46,7 +46,7 @@ public class GalaxyContext {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TransactionTemplate transactionTemplate() {
|
||||
public TransactionTemplate transactionTemplate() {
|
||||
return new TransactionTemplate(transactionManager());
|
||||
}
|
||||
|
||||
|
||||
@@ -13,116 +13,118 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.galaxy.domain;
|
||||
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
/**
|
||||
* @author Vince Bickers
|
||||
* @author Luanne Misquitta
|
||||
*/
|
||||
public class World {
|
||||
|
||||
private final static String REACHABLE_BY_ROCKET = "REACHABLE_BY_ROCKET";
|
||||
private final static String REACHABLE_BY_ROCKET = "REACHABLE_BY_ROCKET";
|
||||
|
||||
private Long id;
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private int moons;
|
||||
private int moons;
|
||||
|
||||
private Float radius;
|
||||
private Float radius;
|
||||
|
||||
private Long updated;
|
||||
private Long updated;
|
||||
|
||||
public Long getUpdated() {
|
||||
return updated;
|
||||
}
|
||||
public Long getUpdated() {
|
||||
return updated;
|
||||
}
|
||||
|
||||
public void setUpdated(long updated) {
|
||||
this.updated = updated;
|
||||
}
|
||||
public void setUpdated(long updated) {
|
||||
this.updated = updated;
|
||||
}
|
||||
|
||||
private Set<World> reachableByRocket = new HashSet<>();
|
||||
|
||||
private Set<World> reachableByRocket = new HashSet<>();
|
||||
public World(String name, int moons) {
|
||||
this.name = name;
|
||||
this.moons = moons;
|
||||
}
|
||||
|
||||
public World(String name, int moons) {
|
||||
this.name = name;
|
||||
this.moons = moons;
|
||||
}
|
||||
public World() {}
|
||||
|
||||
public World() {
|
||||
}
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public int getMoons() {
|
||||
return moons;
|
||||
}
|
||||
|
||||
public int getMoons() {
|
||||
return moons;
|
||||
}
|
||||
public void addRocketRouteTo(World otherWorld) {
|
||||
reachableByRocket.add(otherWorld);
|
||||
// symmetric relationship.
|
||||
otherWorld.reachableByRocket.add(this); // bi-directional in domain.
|
||||
}
|
||||
|
||||
public void addRocketRouteTo(World otherWorld) {
|
||||
reachableByRocket.add(otherWorld);
|
||||
// symmetric relationship.
|
||||
otherWorld.reachableByRocket.add(this); // bi-directional in domain.
|
||||
}
|
||||
@Relationship(type = REACHABLE_BY_ROCKET, direction = "UNDIRECTED")
|
||||
public Set<World> getReachableByRocket() {
|
||||
return this.reachableByRocket;
|
||||
}
|
||||
|
||||
@Relationship(type=REACHABLE_BY_ROCKET, direction = "UNDIRECTED")
|
||||
public Set<World> getReachableByRocket() {
|
||||
return this.reachableByRocket;
|
||||
}
|
||||
@Relationship(type = REACHABLE_BY_ROCKET, direction = "UNDIRECTED")
|
||||
public void setReachableByRocket(Set<World> reachableByRocket) {
|
||||
this.reachableByRocket.clear();
|
||||
this.reachableByRocket = reachableByRocket;
|
||||
}
|
||||
|
||||
@Relationship(type=REACHABLE_BY_ROCKET , direction = "UNDIRECTED")
|
||||
public void setReachableByRocket(Set<World> reachableByRocket) {
|
||||
this.reachableByRocket.clear();
|
||||
this.reachableByRocket = reachableByRocket;
|
||||
}
|
||||
public boolean canBeReachedFrom(World otherWorld) {
|
||||
for (World world : reachableByRocket) {
|
||||
if (world.equals(otherWorld)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canBeReachedFrom(World otherWorld) {
|
||||
for(World world : reachableByRocket) {
|
||||
if(world.equals(otherWorld)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public Float getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
public Float getRadius() {
|
||||
return radius;
|
||||
}
|
||||
public void setRadius(Float radius) {
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public void setRadius(Float radius) {
|
||||
this.radius = radius;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
World world = (World) o;
|
||||
|
||||
World world = (World) o;
|
||||
if (moons != world.moons)
|
||||
return false;
|
||||
if (id != null ? !id.equals(world.id) : world.id != null)
|
||||
return false;
|
||||
return !(name != null ? !name.equals(world.name) : world.name != null);
|
||||
}
|
||||
|
||||
if (moons != world.moons) return false;
|
||||
if (id != null ? !id.equals(world.id) : world.id != null) return false;
|
||||
return !(name != null ? !name.equals(world.name) : world.name != null);
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
result = 31 * result + moons;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
result = 31 * result + moons;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("World{name='%s', moons=%d}", name, moons);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("World{name='%s', moons=%d}", name, moons);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.neo4j.ogm.model.Result;
|
||||
import org.springframework.data.neo4j.annotation.Query;
|
||||
import org.springframework.data.neo4j.examples.galaxy.domain.World;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.Neo4jRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
@@ -27,12 +26,12 @@ import org.springframework.stereotype.Repository;
|
||||
@Repository
|
||||
public interface WorldRepository extends GraphRepository<World> {
|
||||
|
||||
@Query("MATCH (n:World) SET n.updated=timestamp()")
|
||||
void touchAllWorlds();
|
||||
@Query("MATCH (n:World) SET n.updated=timestamp()")
|
||||
void touchAllWorlds();
|
||||
|
||||
@Query("MATCH (n:World) SET n.updated=timestamp()")
|
||||
Result touchAllWorldsWithStatistics();
|
||||
@Query("MATCH (n:World) SET n.updated=timestamp()")
|
||||
Result touchAllWorldsWithStatistics();
|
||||
|
||||
World findByName(String name);
|
||||
World findByName(String name);
|
||||
|
||||
}
|
||||
|
||||
@@ -36,11 +36,9 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Transactional
|
||||
public class GalaxyService {
|
||||
|
||||
@Autowired
|
||||
private WorldRepository worldRepository;
|
||||
@Autowired private WorldRepository worldRepository;
|
||||
|
||||
@Autowired
|
||||
Session session;
|
||||
@Autowired Session session;
|
||||
|
||||
public long getNumberOfWorlds() {
|
||||
return worldRepository.count();
|
||||
@@ -89,13 +87,13 @@ public class GalaxyService {
|
||||
mars.addRocketRouteTo(earth);
|
||||
|
||||
// todo: handle bi-directional automatically
|
||||
//earth.addRocketRouteTo(mars);
|
||||
// earth.addRocketRouteTo(mars);
|
||||
|
||||
// this is a bit silly
|
||||
worldRepository.save(mars);
|
||||
|
||||
// todo: handle-bidirectional automatically
|
||||
//worldRepository.save(earth);
|
||||
// worldRepository.save(earth);
|
||||
|
||||
worlds.add(earth);
|
||||
worlds.add(mars);
|
||||
@@ -163,7 +161,6 @@ public class GalaxyService {
|
||||
return session.loadAll(World.class, new Filter(propertyName, propertyValue), depth);
|
||||
}
|
||||
|
||||
|
||||
public Iterable<World> findAllWorlds(Pagination paging) {
|
||||
return session.loadAll(World.class, paging, 0);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = {AdultService.class})
|
||||
@ComponentScan(basePackageClasses = { AdultService.class })
|
||||
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.jsr303.repo")
|
||||
@EnableTransactionManagement
|
||||
public class JSR303Context {
|
||||
|
||||
@@ -35,18 +35,16 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
* @author Vince Bickers
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@ContextConfiguration(classes = {WebConfiguration.class, JSR303Context.class})
|
||||
@ContextConfiguration(classes = { WebConfiguration.class, JSR303Context.class })
|
||||
@WebAppConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class JSR303IT extends MultiDriverTestClass {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Autowired
|
||||
private AdultService service;
|
||||
@Autowired private AdultService service;
|
||||
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
@Autowired WebApplicationContext wac;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -61,11 +59,7 @@ public class JSR303IT extends MultiDriverTestClass {
|
||||
Adult adult = new Adult("Peter", 18);
|
||||
String json = objectMapper.writeValueAsString(adult);
|
||||
|
||||
mockMvc.perform(
|
||||
post("/adults")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(json))
|
||||
.andExpect(status().isOk());
|
||||
mockMvc.perform(post("/adults").contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -74,10 +68,7 @@ public class JSR303IT extends MultiDriverTestClass {
|
||||
Adult adult = new Adult("Peter", 16);
|
||||
String json = objectMapper.writeValueAsString(adult);
|
||||
|
||||
mockMvc.perform(
|
||||
post("/adults")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(json))
|
||||
mockMvc.perform(post("/adults").contentType(MediaType.APPLICATION_JSON).content(json))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@@ -87,10 +78,7 @@ public class JSR303IT extends MultiDriverTestClass {
|
||||
Adult adult = new Adult(null, 21);
|
||||
String json = objectMapper.writeValueAsString(adult);
|
||||
|
||||
mockMvc.perform(
|
||||
post("/adults")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(json))
|
||||
mockMvc.perform(post("/adults").contentType(MediaType.APPLICATION_JSON).content(json))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@@ -100,10 +88,7 @@ public class JSR303IT extends MultiDriverTestClass {
|
||||
Adult adult = new Adult("A", 21);
|
||||
String json = objectMapper.writeValueAsString(adult);
|
||||
|
||||
mockMvc.perform(
|
||||
post("/adults")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(json))
|
||||
mockMvc.perform(post("/adults").contentType(MediaType.APPLICATION_JSON).content(json))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||
* @author Vince Bickers
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan({"org.springframework.data.neo4j.examples.jsr303.controller"})
|
||||
@ComponentScan({ "org.springframework.data.neo4j.examples.jsr303.controller" })
|
||||
@EnableWebMvc
|
||||
public class WebConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Bean(name="validator")
|
||||
public LocalValidatorFactoryBean validator() {
|
||||
return new LocalValidatorFactoryBean();
|
||||
}
|
||||
@Bean(name = "validator")
|
||||
public LocalValidatorFactoryBean validator() {
|
||||
return new LocalValidatorFactoryBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,16 +13,21 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.jsr303.controller;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.ValidationException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.examples.jsr303.domain.Adult;
|
||||
import org.springframework.data.neo4j.examples.jsr303.service.AdultService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.ValidationException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author Vince Bickers
|
||||
@@ -30,22 +35,21 @@ import javax.validation.ValidationException;
|
||||
@Controller
|
||||
public class AdultController {
|
||||
|
||||
@Autowired
|
||||
private AdultService service;
|
||||
@Autowired private AdultService service;
|
||||
|
||||
@RequestMapping(value = "/adults", method = RequestMethod.POST, consumes = "application/json")
|
||||
@ResponseBody
|
||||
public Adult create (@Valid @RequestBody Adult entity, BindingResult bindingResult) {
|
||||
// in practice we'd do a bit more than this...
|
||||
if (bindingResult.hasErrors()) {
|
||||
throw new ValidationException("oops");
|
||||
}
|
||||
return service.save(entity);
|
||||
}
|
||||
@RequestMapping(value = "/adults", method = RequestMethod.POST, consumes = "application/json")
|
||||
@ResponseBody
|
||||
public Adult create(@Valid @RequestBody Adult entity, BindingResult bindingResult) {
|
||||
// in practice we'd do a bit more than this...
|
||||
if (bindingResult.hasErrors()) {
|
||||
throw new ValidationException("oops");
|
||||
}
|
||||
return service.save(entity);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ValidationException.class)
|
||||
@ResponseBody
|
||||
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
|
||||
public void handleException(ValidationException ve) { }
|
||||
@ExceptionHandler(ValidationException.class)
|
||||
@ResponseBody
|
||||
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
|
||||
public void handleException(ValidationException ve) {}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,20 +27,15 @@ import org.neo4j.ogm.annotation.NodeEntity;
|
||||
@NodeEntity
|
||||
public class Adult {
|
||||
|
||||
@GraphId
|
||||
private Long id;
|
||||
@GraphId private Long id;
|
||||
|
||||
@NotNull @Size(min = 2, max = 50)
|
||||
private String name;
|
||||
@NotNull @Size(min = 2, max = 50) private String name;
|
||||
|
||||
@Min(18)
|
||||
private Integer age;
|
||||
@Min(18) private Integer age;
|
||||
|
||||
@AssertTrue
|
||||
private boolean votingAge;
|
||||
@AssertTrue private boolean votingAge;
|
||||
|
||||
public Adult() {
|
||||
}
|
||||
public Adult() {}
|
||||
|
||||
public Adult(String name, Integer age) {
|
||||
this.name = name;
|
||||
@@ -48,7 +43,6 @@ public class Adult {
|
||||
this.votingAge = true;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -21,5 +21,4 @@ import org.springframework.stereotype.Repository;
|
||||
* @author Vince Bickers
|
||||
*/
|
||||
@Repository
|
||||
public interface AdultRepository extends Neo4jRepository<Adult, Long> {
|
||||
}
|
||||
public interface AdultRepository extends Neo4jRepository<Adult, Long> {}
|
||||
|
||||
@@ -24,10 +24,9 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class AdultService {
|
||||
|
||||
@Autowired
|
||||
private AdultRepository repository;
|
||||
@Autowired private AdultRepository repository;
|
||||
|
||||
public Adult save(Adult adult) {
|
||||
return repository.save(adult);
|
||||
}
|
||||
public Adult save(Adult adult) {
|
||||
return repository.save(adult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,18 @@ package org.springframework.data.neo4j.examples.movies;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.neo4j.ogm.testutil.GraphTestUtils.*;
|
||||
import static org.springframework.data.repository.query.parser.Part.Type.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
@@ -38,8 +42,20 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.neo4j.examples.movies.context.MoviesContext;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.*;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.*;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.Actor;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.Cinema;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.Genre;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.Movie;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.ReleasedMovie;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.TempMovie;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.User;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.AbstractAnnotatedEntityRepository;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.AbstractEntityRepository;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.ActorRepository;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.CinemaRepository;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.RatingRepository;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.TempMovieRepository;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.UserRepository;
|
||||
import org.springframework.data.neo4j.examples.movies.service.UserService;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -54,7 +70,7 @@ import org.springframework.transaction.support.TransactionTemplate;
|
||||
* @author Vince Bickers
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@ContextConfiguration(classes = {MoviesContext.class})
|
||||
@ContextConfiguration(classes = { MoviesContext.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
|
||||
@@ -62,26 +78,16 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
|
||||
private static GraphDatabaseService graphDatabaseService;
|
||||
|
||||
@Autowired
|
||||
PlatformTransactionManager platformTransactionManager;
|
||||
@Autowired
|
||||
private Session session;
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private CinemaRepository cinemaRepository;
|
||||
@Autowired
|
||||
private AbstractAnnotatedEntityRepository abstractAnnotatedEntityRepository;
|
||||
@Autowired
|
||||
private AbstractEntityRepository abstractEntityRepository;
|
||||
@Autowired
|
||||
private TempMovieRepository tempMovieRepository;
|
||||
@Autowired
|
||||
private ActorRepository actorRepository;
|
||||
@Autowired
|
||||
private RatingRepository ratingRepository;
|
||||
@Autowired PlatformTransactionManager platformTransactionManager;
|
||||
@Autowired private Session session;
|
||||
@Autowired private UserRepository userRepository;
|
||||
@Autowired private UserService userService;
|
||||
@Autowired private CinemaRepository cinemaRepository;
|
||||
@Autowired private AbstractAnnotatedEntityRepository abstractAnnotatedEntityRepository;
|
||||
@Autowired private AbstractEntityRepository abstractEntityRepository;
|
||||
@Autowired private TempMovieRepository tempMovieRepository;
|
||||
@Autowired private ActorRepository actorRepository;
|
||||
@Autowired private RatingRepository ratingRepository;
|
||||
|
||||
private TransactionTemplate transactionTemplate;
|
||||
|
||||
@@ -112,7 +118,6 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
assertSameGraph(graphDatabaseService, "CREATE (u:User:Person)");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldSaveReleasedMovie() {
|
||||
|
||||
@@ -125,8 +130,8 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
abstractAnnotatedEntityRepository.save(releasedMovie);
|
||||
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE (m:ReleasedMovie:AbstractAnnotatedEntity {cinemaRelease:'1994-09-10T00:00:00.000Z'," +
|
||||
"cannesRelease:768700800000,title:'Pulp Fiction'})");
|
||||
"CREATE (m:ReleasedMovie:AbstractAnnotatedEntity {cinemaRelease:'1994-09-10T00:00:00.000Z',"
|
||||
+ "cannesRelease:768700800000,title:'Pulp Fiction'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -146,14 +151,14 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
public void shouldSaveMovie() {
|
||||
|
||||
Movie movie = new Movie("Pulp Fiction");
|
||||
movie.setTags(new String[]{"cool", "classic"});
|
||||
movie.setImage(new byte[]{1, 2, 3});
|
||||
movie.setTags(new String[] { "cool", "classic" });
|
||||
movie.setImage(new byte[] { 1, 2, 3 });
|
||||
|
||||
abstractEntityRepository.save(movie);
|
||||
|
||||
// byte arrays have to be transferred with a JSON-supported format. Base64 is the default.
|
||||
assertSameGraph(graphDatabaseService, "CREATE (m:Movie {name:'Pulp Fiction', tags:['cool','classic'], " +
|
||||
"image:'AQID'})");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE (m:Movie {name:'Pulp Fiction', tags:['cool','classic'], " + "image:'AQID'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -171,12 +176,10 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE (:User:Person {name:'Michal'})," +
|
||||
"(:User:Person {name:'Vince'})," +
|
||||
"(:User:Person {name:'Adam'})");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE (:User:Person {name:'Michal'})," + "(:User:Person {name:'Vince'})," + "(:User:Person {name:'Adam'})");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldSaveUsers2() {
|
||||
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
|
||||
@@ -192,9 +195,8 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE (:User:Person {name:'Michal'})," +
|
||||
"(:User:Person {name:'Vince'})," +
|
||||
"(:User:Person {name:'Adam'})");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE (:User:Person {name:'Michal'})," + "(:User:Person {name:'Vince'})," + "(:User:Person {name:'Adam'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -211,16 +213,15 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
assertSameGraph(graphDatabaseService, "CREATE (u:User:Person {name:'Adam'})");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore // FIXME
|
||||
@Ignore // FIXME
|
||||
// this test expects the session/tx to check for dirty objects, which it currently does not do
|
||||
// you must save objects explicitly.
|
||||
public void shouldUpdateUserUsingTransactionalService() {
|
||||
User user = new User("Michal");
|
||||
userRepository.save(user);
|
||||
|
||||
userService.updateUser(user, "Adam"); //notice userRepository.save(..) isn't called,
|
||||
userService.updateUser(user, "Adam"); // notice userRepository.save(..) isn't called,
|
||||
// not even in the service impl!
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE (u:User {name:'Adam'})");
|
||||
@@ -292,7 +293,6 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldHandleMultipleConcurrentRequests() throws InterruptedException, Neo4jFailedToStartException {
|
||||
|
||||
@@ -319,7 +319,8 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void shouldInterceptOGMExceptions() {
|
||||
ratingRepository.findAll(0); // ratings are REs and must be found to at least depth 1 in order to get the start and end nodes
|
||||
ratingRepository.findAll(0); // ratings are REs and must be found to at least depth 1 in order to get the start and
|
||||
// end nodes
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -329,7 +330,8 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
|
||||
userRepository.save(user);
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -341,14 +343,10 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
|
||||
userRepository.save(user);
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE " +
|
||||
"(u:User:Person {name:'Michal'})," +
|
||||
"(g1:Genre {name:'Drama'})," +
|
||||
"(g2:Genre {name:'Historical'})," +
|
||||
"(g3:Genre {name:'Thriller'})," +
|
||||
"(u)-[:INTERESTED]->(g1)," +
|
||||
"(u)-[:INTERESTED]->(g2)," +
|
||||
"(u)-[:INTERESTED]->(g3)");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE " + "(u:User:Person {name:'Michal'})," + "(g1:Genre {name:'Drama'}),"
|
||||
+ "(g2:Genre {name:'Historical'})," + "(g3:Genre {name:'Thriller'})," + "(u)-[:INTERESTED]->(g1),"
|
||||
+ "(u)-[:INTERESTED]->(g2)," + "(u)-[:INTERESTED]->(g3)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -358,7 +356,8 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
|
||||
userRepository.save(user, 1);
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -379,15 +378,11 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(v:User:Person {name:'Vince'})," +
|
||||
"(g:Genre {name:'Drama'})," +
|
||||
"(m)-[:INTERESTED]->(g)," +
|
||||
"(v)-[:INTERESTED]->(g)");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE " + "(m:User:Person {name:'Michal'})," + "(v:User:Person {name:'Vince'})," + "(g:Genre {name:'Drama'}),"
|
||||
+ "(m)-[:INTERESTED]->(g)," + "(v)-[:INTERESTED]->(g)");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldSaveUserButNotGenre() {
|
||||
User user = new User("Michal");
|
||||
@@ -416,13 +411,10 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(g:Genre {name:'New Drama'})," +
|
||||
"(m)-[:INTERESTED]->(g)");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'New Drama'})," + "(m)-[:INTERESTED]->(g)");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldRemoveGenreFromUser() {
|
||||
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
|
||||
@@ -440,9 +432,7 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(g:Genre {name:'Drama'})");
|
||||
assertSameGraph(graphDatabaseService, "CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'Drama'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -460,12 +450,9 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(g:Genre {name:'Drama'})");
|
||||
assertSameGraph(graphDatabaseService, "CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'Drama'})");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldAddNewVisitorToCinema() {
|
||||
Cinema cinema = new Cinema("Odeon");
|
||||
@@ -473,10 +460,8 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
|
||||
cinemaRepository.save(cinema);
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(c:Theatre {name:'Odeon', capacity:0})," +
|
||||
"(m)-[:VISITED]->(c)");
|
||||
assertSameGraph(graphDatabaseService, "CREATE " + "(m:User:Person {name:'Michal'}),"
|
||||
+ "(c:Theatre {name:'Odeon', capacity:0})," + "(m)-[:VISITED]->(c)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -494,10 +479,8 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(c:Theatre {name:'Odeon', capacity:0})," +
|
||||
"(m)-[:VISITED]->(c)");
|
||||
assertSameGraph(graphDatabaseService, "CREATE " + "(m:User:Person {name:'Michal'}),"
|
||||
+ "(c:Theatre {name:'Odeon', capacity:0})," + "(m)-[:VISITED]->(c)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -512,9 +495,11 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
});
|
||||
|
||||
try {
|
||||
assertSameGraph(graphDatabaseService, "CREATE (m:User {name:'Michal'})-[:FRIEND_OF]->(a:User:Person {name:'Adam'})");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE (m:User {name:'Michal'})-[:FRIEND_OF]->(a:User:Person {name:'Adam'})");
|
||||
} catch (AssertionError error) {
|
||||
assertSameGraph(graphDatabaseService, "CREATE (m:User:Person {name:'Michal'})<-[:FRIEND_OF]-(a:User:Person {name:'Adam'})");
|
||||
assertSameGraph(graphDatabaseService,
|
||||
"CREATE (m:User:Person {name:'Michal'})<-[:FRIEND_OF]-(a:User:Person {name:'Adam'})");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,8 +544,8 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
|
||||
User michal = ((Iterable<User>) findByProperty(User.class, "name", "Michal")).iterator().next();
|
||||
|
||||
assertSameGraph(graphDatabaseService, "CREATE (u:User:Person {name:'Michal'})-[:RATED {stars:5, " +
|
||||
"comment:'Best movie ever', ratingTimestamp:0}]->(m:Movie {name:'Pulp Fiction'})");
|
||||
assertSameGraph(graphDatabaseService, "CREATE (u:User:Person {name:'Michal'})-[:RATED {stars:5, "
|
||||
+ "comment:'Best movie ever', ratingTimestamp:0}]->(m:Movie {name:'Pulp Fiction'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -570,15 +555,16 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
TempMovie movie = new TempMovie("Pulp Fiction");
|
||||
//Save the movie
|
||||
// Save the movie
|
||||
movie = tempMovieRepository.save(movie);
|
||||
|
||||
//Create a new user and rate an existing movie
|
||||
// Create a new user and rate an existing movie
|
||||
User user = new User("Michal");
|
||||
user.rate(movie, 5, "Best movie ever");
|
||||
userRepository.save(user);
|
||||
|
||||
TempMovie tempMovie = ((Iterable<TempMovie>) findByProperty(TempMovie.class, "name", "Pulp Fiction")).iterator().next();
|
||||
TempMovie tempMovie = ((Iterable<TempMovie>) findByProperty(TempMovie.class, "name", "Pulp Fiction")).iterator()
|
||||
.next();
|
||||
assertEquals(1, tempMovie.getRatings().size());
|
||||
}
|
||||
});
|
||||
@@ -594,10 +580,10 @@ public class MoviesIntegrationIT extends MultiDriverTestClass {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
TempMovie movie = new TempMovie("Pulp Fiction");
|
||||
//Save the movie
|
||||
// Save the movie
|
||||
movie = tempMovieRepository.save(movie);
|
||||
|
||||
//Create a new user and rate an existing movie
|
||||
// Create a new user and rate an existing movie
|
||||
User user = new User("Michal");
|
||||
user.rate(movie, 5, "Best movie ever");
|
||||
userRepository.save(user);
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan({"org.springframework.data.neo4j.examples.movies.service"})
|
||||
@ComponentScan({ "org.springframework.data.neo4j.examples.movies.service" })
|
||||
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.movies.repo")
|
||||
@EnableTransactionManagement
|
||||
public class MoviesContext {
|
||||
|
||||
@@ -22,6 +22,5 @@ import org.neo4j.ogm.annotation.NodeEntity;
|
||||
@NodeEntity
|
||||
public abstract class AbstractAnnotatedEntity {
|
||||
|
||||
@GraphId
|
||||
Long nodeId;
|
||||
@GraphId Long nodeId;
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ package org.springframework.data.neo4j.examples.movies.domain;
|
||||
*/
|
||||
public abstract class AbstractEntity {
|
||||
|
||||
Long id;
|
||||
Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,40 +13,37 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.movies.domain;
|
||||
|
||||
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
|
||||
/**
|
||||
* @author Michal Bachman
|
||||
*/
|
||||
public class Actor{
|
||||
public class Actor {
|
||||
|
||||
@GraphId
|
||||
Long nodeId;
|
||||
String id;
|
||||
String name;
|
||||
@GraphId Long nodeId;
|
||||
String id;
|
||||
String name;
|
||||
|
||||
public Actor() {
|
||||
}
|
||||
public Actor() {}
|
||||
|
||||
public Actor(String id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
public Actor(String id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.movies.domain;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.annotation.Property;
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Michal Bachman
|
||||
* @author Luanne Misquitta
|
||||
@@ -31,19 +31,15 @@ public class Cinema {
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
@Property(name = "city")
|
||||
private String location;
|
||||
@Property(name = "city") private String location;
|
||||
|
||||
@Relationship(type = "VISITED", direction = Relationship.INCOMING)
|
||||
private Set<User> visited = new HashSet<>();
|
||||
@Relationship(type = "VISITED", direction = Relationship.INCOMING) private Set<User> visited = new HashSet<>();
|
||||
|
||||
@Relationship(type = "BLOCKBUSTER", direction = Relationship.OUTGOING)
|
||||
private TempMovie blockbusterOfTheWeek;
|
||||
@Relationship(type = "BLOCKBUSTER", direction = Relationship.OUTGOING) private TempMovie blockbusterOfTheWeek;
|
||||
|
||||
private int capacity;
|
||||
|
||||
public Cinema() {
|
||||
}
|
||||
public Cinema() {}
|
||||
|
||||
public Cinema(String name) {
|
||||
this.name = name;
|
||||
@@ -93,8 +89,10 @@ public class Cinema {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Cinema cinema = (Cinema) o;
|
||||
|
||||
|
||||
@@ -20,6 +20,5 @@ public class Director extends Person {
|
||||
|
||||
private Long id;
|
||||
|
||||
public Director() {
|
||||
}
|
||||
public Director() {}
|
||||
}
|
||||
|
||||
@@ -18,25 +18,24 @@ package org.springframework.data.neo4j.examples.movies.domain;
|
||||
*/
|
||||
public class Genre {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
public Genre() {
|
||||
}
|
||||
public Genre() {}
|
||||
|
||||
public Genre(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public Genre(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,34 +18,33 @@ package org.springframework.data.neo4j.examples.movies.domain;
|
||||
*/
|
||||
public class Movie extends AbstractEntity {
|
||||
|
||||
private String name;
|
||||
private String[] tags;
|
||||
private byte[] image;
|
||||
private String name;
|
||||
private String[] tags;
|
||||
private byte[] image;
|
||||
|
||||
public Movie() {
|
||||
}
|
||||
public Movie() {}
|
||||
|
||||
public Movie(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public Movie(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String[] getTags() {
|
||||
return tags;
|
||||
}
|
||||
public String[] getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(String[] tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
public void setTags(String[] tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public byte[] getImage() {
|
||||
return image;
|
||||
}
|
||||
public byte[] getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(byte[] image) {
|
||||
this.image = image;
|
||||
}
|
||||
public void setImage(byte[] image) {
|
||||
this.image = image;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ public class Person {
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -36,8 +35,10 @@ public class Person {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Person person = (Person) o;
|
||||
|
||||
|
||||
@@ -21,77 +21,75 @@ import org.neo4j.ogm.annotation.StartNode;
|
||||
* @author Michal Bachman
|
||||
*/
|
||||
@RelationshipEntity(type = "RATED")
|
||||
public class Rating implements Comparable{
|
||||
private Long id;
|
||||
public class Rating implements Comparable {
|
||||
private Long id;
|
||||
|
||||
@StartNode
|
||||
private User user;
|
||||
@EndNode
|
||||
private TempMovie movie;
|
||||
private int stars;
|
||||
private String comment;
|
||||
@StartNode private User user;
|
||||
@EndNode private TempMovie movie;
|
||||
private int stars;
|
||||
private String comment;
|
||||
|
||||
private long ratingTimestamp;
|
||||
private long ratingTimestamp;
|
||||
|
||||
public Rating() {}
|
||||
public Rating() {}
|
||||
|
||||
public Rating(User user, TempMovie movie, int stars, String comment) {
|
||||
this.user = user;
|
||||
this.movie = movie;
|
||||
this.stars = stars;
|
||||
this.comment = comment;
|
||||
}
|
||||
public Rating(User user, TempMovie movie, int stars, String comment) {
|
||||
this.user = user;
|
||||
this.movie = movie;
|
||||
this.stars = stars;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public void setMovie(TempMovie movie) {
|
||||
this.movie = movie;
|
||||
}
|
||||
public void setMovie(TempMovie movie) {
|
||||
this.movie = movie;
|
||||
}
|
||||
|
||||
public void setStars(int stars) {
|
||||
this.stars = stars;
|
||||
}
|
||||
public void setStars(int stars) {
|
||||
this.stars = stars;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public TempMovie getMovie() {
|
||||
return movie;
|
||||
}
|
||||
public TempMovie getMovie() {
|
||||
return movie;
|
||||
}
|
||||
|
||||
public int getStars() {
|
||||
return stars;
|
||||
}
|
||||
public int getStars() {
|
||||
return stars;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public long getRatingTimestamp() {
|
||||
return ratingTimestamp;
|
||||
}
|
||||
public long getRatingTimestamp() {
|
||||
return ratingTimestamp;
|
||||
}
|
||||
|
||||
public void setRatingTimestamp(long ratingTimestamp) {
|
||||
this.ratingTimestamp = ratingTimestamp;
|
||||
}
|
||||
public void setRatingTimestamp(long ratingTimestamp) {
|
||||
this.ratingTimestamp = ratingTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
Rating other = (Rating) o;
|
||||
if (stars == ((Rating) o).getStars()) {
|
||||
return getUser().getName().compareTo(other.getUser().getName());
|
||||
}
|
||||
return stars - other.getStars();
|
||||
}
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
Rating other = (Rating) o;
|
||||
if (stars == ((Rating) o).getStars()) {
|
||||
return getUser().getName().compareTo(other.getUser().getName());
|
||||
}
|
||||
return stars - other.getStars();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,43 +13,40 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.movies.domain;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.neo4j.ogm.annotation.Property;
|
||||
import org.neo4j.ogm.annotation.typeconversion.DateLong;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Michal Bachman
|
||||
*/
|
||||
//the fields here will move to Movie, this separate class exists temporarily after its tests pass
|
||||
// the fields here will move to Movie, this separate class exists temporarily after its tests pass
|
||||
public class ReleasedMovie extends AbstractAnnotatedEntity {
|
||||
|
||||
private String title;
|
||||
private String title;
|
||||
|
||||
@Property(name = "cinemaRelease")
|
||||
private Date released;
|
||||
@Property(name = "cinemaRelease") private Date released;
|
||||
|
||||
@DateLong
|
||||
private Date cannesRelease;
|
||||
@DateLong private Date cannesRelease;
|
||||
|
||||
public ReleasedMovie() {
|
||||
}
|
||||
public ReleasedMovie() {}
|
||||
|
||||
public ReleasedMovie(String title, Date released, Date cannesRelease) {
|
||||
this.title = title;
|
||||
this.released = released;
|
||||
this.cannesRelease = cannesRelease;
|
||||
}
|
||||
public ReleasedMovie(String title, Date released, Date cannesRelease) {
|
||||
this.title = title;
|
||||
this.released = released;
|
||||
this.cannesRelease = cannesRelease;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Date getReleased() {
|
||||
return released;
|
||||
}
|
||||
public Date getReleased() {
|
||||
return released;
|
||||
}
|
||||
|
||||
public Date getCannesRelease() {
|
||||
return cannesRelease;
|
||||
}
|
||||
public Date getCannesRelease() {
|
||||
return cannesRelease;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,40 +13,38 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.movies.domain;
|
||||
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
/**
|
||||
* @author Michal Bachman
|
||||
* @author Luanne Misquitta
|
||||
*/
|
||||
//todo merge with movie when tests fixed
|
||||
// todo merge with movie when tests fixed
|
||||
@NodeEntity(label = "Movie")
|
||||
public class TempMovie extends AbstractEntity {
|
||||
|
||||
private String name;
|
||||
@Relationship(type = "RATED", direction = Relationship.INCOMING)
|
||||
private Set<Rating> ratings = new HashSet<>();
|
||||
private String name;
|
||||
@Relationship(type = "RATED", direction = Relationship.INCOMING) private Set<Rating> ratings = new HashSet<>();
|
||||
|
||||
public TempMovie() {
|
||||
}
|
||||
public TempMovie() {}
|
||||
|
||||
public TempMovie(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public TempMovie(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void addRating(Rating rating) {
|
||||
ratings.add(rating);
|
||||
}
|
||||
public void addRating(Rating rating) {
|
||||
ratings.add(rating);
|
||||
}
|
||||
|
||||
public Set<Rating> getRatings() {
|
||||
return ratings;
|
||||
}
|
||||
public Set<Rating> getRatings() {
|
||||
return ratings;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,80 +13,76 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.movies.domain;
|
||||
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
/**
|
||||
* @author Michal Bachman
|
||||
* @author Luanne Misquitta
|
||||
*/
|
||||
public class User extends Person{
|
||||
public class User extends Person {
|
||||
|
||||
private String middleName;
|
||||
private String surname;
|
||||
private String middleName;
|
||||
private String surname;
|
||||
|
||||
private Collection<Genre> interested = new HashSet<>();
|
||||
private Collection<Genre> interested = new HashSet<>();
|
||||
|
||||
@Relationship(type = "FRIEND_OF", direction = Relationship.UNDIRECTED)
|
||||
private Collection<User> friends = new HashSet<>();
|
||||
@Relationship(type = "FRIEND_OF",
|
||||
direction = Relationship.UNDIRECTED) private Collection<User> friends = new HashSet<>();
|
||||
|
||||
@Relationship(type = "RATED")
|
||||
private Set<Rating> ratings = new HashSet<>();
|
||||
@Relationship(type = "RATED") private Set<Rating> ratings = new HashSet<>();
|
||||
|
||||
public User() {
|
||||
}
|
||||
public User() {}
|
||||
|
||||
public User(String name) {
|
||||
setName(name);
|
||||
}
|
||||
public User(String name) {
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public User(String name, String surname) {
|
||||
setName(name);
|
||||
this.surname = surname;
|
||||
}
|
||||
public User(String name, String surname) {
|
||||
setName(name);
|
||||
this.surname = surname;
|
||||
}
|
||||
|
||||
public void interestedIn(Genre genre) {
|
||||
interested.add(genre);
|
||||
}
|
||||
public void interestedIn(Genre genre) {
|
||||
interested.add(genre);
|
||||
}
|
||||
|
||||
public void notInterestedIn(Genre genre) {
|
||||
interested.remove(genre);
|
||||
}
|
||||
public void notInterestedIn(Genre genre) {
|
||||
interested.remove(genre);
|
||||
}
|
||||
|
||||
public void befriend(User user) {
|
||||
friends.add(user);
|
||||
user.friends.add(this);
|
||||
}
|
||||
public void befriend(User user) {
|
||||
friends.add(user);
|
||||
user.friends.add(this);
|
||||
}
|
||||
|
||||
public Rating rate(TempMovie movie, int stars, String comment) {
|
||||
Rating rating = new Rating(this, movie, stars, comment);
|
||||
movie.addRating(rating);
|
||||
ratings.add(rating);
|
||||
return rating;
|
||||
}
|
||||
|
||||
public Rating rate(TempMovie movie, int stars, String comment) {
|
||||
Rating rating = new Rating(this, movie, stars, comment);
|
||||
movie.addRating(rating);
|
||||
ratings.add(rating);
|
||||
return rating;
|
||||
}
|
||||
public Collection<User> getFriends() {
|
||||
return friends;
|
||||
}
|
||||
|
||||
public Collection<User> getFriends() {
|
||||
return friends;
|
||||
}
|
||||
public String getMiddleName() {
|
||||
return middleName;
|
||||
}
|
||||
|
||||
public String getMiddleName()
|
||||
{
|
||||
return middleName;
|
||||
}
|
||||
public Set<Rating> getRatings() {
|
||||
return ratings;
|
||||
}
|
||||
|
||||
public Set<Rating> getRatings() {
|
||||
return ratings;
|
||||
}
|
||||
public void setMiddleName(String middleName) {
|
||||
this.middleName = middleName;
|
||||
}
|
||||
|
||||
public void setMiddleName(String middleName) {
|
||||
this.middleName = middleName;
|
||||
}
|
||||
|
||||
public String getSurname() {
|
||||
return surname;
|
||||
}
|
||||
public String getSurname() {
|
||||
return surname;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,25 +23,24 @@ import org.springframework.data.neo4j.annotation.QueryResult;
|
||||
@QueryResult
|
||||
public class CinemaQueryResult {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
public CinemaQueryResult() {
|
||||
}
|
||||
public CinemaQueryResult() {}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,12 @@ import org.springframework.data.neo4j.annotation.QueryResult;
|
||||
@QueryResult
|
||||
public interface CinemaQueryResultInterface {
|
||||
|
||||
Long getId();
|
||||
Long getId();
|
||||
|
||||
void setId(Long id);
|
||||
void setId(Long id);
|
||||
|
||||
String getName();
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
void setName(String name);
|
||||
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ public class CinemaQueryResultInterfaceImpl implements CinemaQueryResultInterfac
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
public CinemaQueryResultInterfaceImpl() {
|
||||
}
|
||||
public CinemaQueryResultInterfaceImpl() {}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
|
||||
@@ -31,41 +31,40 @@ import org.springframework.data.neo4j.examples.movies.domain.User;
|
||||
@QueryResult
|
||||
public class EntityWrappingQueryResult {
|
||||
|
||||
private User user;
|
||||
private Set<User> friends;
|
||||
private List<Rating> ratings;
|
||||
private TempMovie[] movies;
|
||||
private float avgRating;
|
||||
private List<Float> allRatings;
|
||||
private Collection<Map<String, Object>> literalMap;
|
||||
private User user;
|
||||
private Set<User> friends;
|
||||
private List<Rating> ratings;
|
||||
private TempMovie[] movies;
|
||||
private float avgRating;
|
||||
private List<Float> allRatings;
|
||||
private Collection<Map<String, Object>> literalMap;
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
public Set<User> getFriends() {
|
||||
return friends;
|
||||
}
|
||||
|
||||
public Set<User> getFriends() {
|
||||
return friends;
|
||||
}
|
||||
public List<Rating> getRatings() {
|
||||
return ratings;
|
||||
}
|
||||
|
||||
public List<Rating> getRatings() {
|
||||
return ratings;
|
||||
}
|
||||
public float getAvgRating() {
|
||||
return avgRating;
|
||||
}
|
||||
|
||||
public float getAvgRating() {
|
||||
return avgRating;
|
||||
}
|
||||
public TempMovie[] getMovies() {
|
||||
return movies;
|
||||
}
|
||||
|
||||
public TempMovie[] getMovies() {
|
||||
return movies;
|
||||
}
|
||||
public List<Float> getAllRatings() {
|
||||
return allRatings;
|
||||
}
|
||||
|
||||
public List<Float> getAllRatings() {
|
||||
return allRatings;
|
||||
}
|
||||
|
||||
public Collection<Map<String, Object>> getLiteralMap() {
|
||||
return literalMap;
|
||||
}
|
||||
public Collection<Map<String, Object>> getLiteralMap() {
|
||||
return literalMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,6 @@ package org.springframework.data.neo4j.examples.movies.domain.queryresult;
|
||||
|
||||
public enum Gender {
|
||||
|
||||
FEMALE, MALE;
|
||||
FEMALE, MALE;
|
||||
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
package org.springframework.data.neo4j.examples.movies.domain.queryresult;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.QueryResult;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.QueryResult;
|
||||
|
||||
/**
|
||||
* A {@link QueryResult} that contains rich types.
|
||||
*
|
||||
@@ -27,24 +27,24 @@ import java.math.BigInteger;
|
||||
@QueryResult
|
||||
public class RichUserQueryResult {
|
||||
|
||||
private Gender userGender; // should be handled by default type conversion
|
||||
private String userName;
|
||||
private BigInteger userAccount;
|
||||
private BigDecimal[] userDeposits;
|
||||
private Gender userGender; // should be handled by default type conversion
|
||||
private String userName;
|
||||
private BigInteger userAccount;
|
||||
private BigDecimal[] userDeposits;
|
||||
|
||||
public Gender getUserGender() {
|
||||
return userGender;
|
||||
}
|
||||
public Gender getUserGender() {
|
||||
return userGender;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public BigInteger getUserAccount() {
|
||||
return userAccount;
|
||||
}
|
||||
public BigInteger getUserAccount() {
|
||||
return userAccount;
|
||||
}
|
||||
|
||||
public BigDecimal[] getUserDeposits() {
|
||||
return userDeposits;
|
||||
}
|
||||
}
|
||||
public BigDecimal[] getUserDeposits() {
|
||||
return userDeposits;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,93 +19,91 @@ import org.springframework.data.neo4j.annotation.QueryResult;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.UserRepository;
|
||||
|
||||
/**
|
||||
* Example POJO {@link QueryResult} to test mapping onto arbitrary objects, even for properties that are on the nodes but not in
|
||||
* the entity classes.
|
||||
* Example POJO {@link QueryResult} to test mapping onto arbitrary objects, even for properties that are on the nodes
|
||||
* but not in the entity classes.
|
||||
*
|
||||
* @see UserRepository
|
||||
*
|
||||
* @author Adam George
|
||||
* @author Luanne Misquitta
|
||||
*/
|
||||
@QueryResult
|
||||
public class UserQueryResult {
|
||||
|
||||
private Long id;
|
||||
Long userId;
|
||||
private String userName;
|
||||
private int age;
|
||||
private Long id;
|
||||
Long userId;
|
||||
private String userName;
|
||||
private int age;
|
||||
|
||||
UserQueryResult() {
|
||||
// default constructor for OGM
|
||||
}
|
||||
UserQueryResult() {
|
||||
// default constructor for OGM
|
||||
}
|
||||
|
||||
public UserQueryResult(String name, int age) {
|
||||
this.userName = name;
|
||||
this.age = age;
|
||||
}
|
||||
public UserQueryResult(String name, int age) {
|
||||
this.userName = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String name) {
|
||||
this.userName = name;
|
||||
}
|
||||
public void setUserName(String name) {
|
||||
this.userName = name;
|
||||
}
|
||||
|
||||
@Property(name = "user.age")
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
@Property(name = "user.age")
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
@Property(name = "user.age")
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
@Property(name = "user.age")
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 23;
|
||||
int result = 1;
|
||||
result = prime * result + age;
|
||||
result = prime * result + ((userName == null) ? 0 : userName.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 23;
|
||||
int result = 1;
|
||||
result = prime * result + age;
|
||||
result = prime * result + ((userName == null) ? 0 : userName.hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
UserQueryResult other = (UserQueryResult) obj;
|
||||
if (age != other.age)
|
||||
return false;
|
||||
if (userName == null) {
|
||||
if (other.userName != null)
|
||||
return false;
|
||||
} else if (!userName.equals(other.userName))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
UserQueryResult other = (UserQueryResult) obj;
|
||||
if (age != other.age)
|
||||
return false;
|
||||
if (userName == null) {
|
||||
if (other.userName != null)
|
||||
return false;
|
||||
} else if (!userName.equals(other.userName))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilder.toString(this);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilder.toString(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,19 +19,19 @@ import org.springframework.data.neo4j.examples.movies.domain.User;
|
||||
import org.springframework.data.neo4j.examples.movies.repo.UserRepository;
|
||||
|
||||
/**
|
||||
* Example interface annotated with {@link QueryResult} to test mapping onto proxied objects, where only getter methods are
|
||||
* needed to define the mapped result columns.
|
||||
* Example interface annotated with {@link QueryResult} to test mapping onto proxied objects, where only getter methods
|
||||
* are needed to define the mapped result columns.
|
||||
*
|
||||
* @see UserRepository
|
||||
*/
|
||||
@QueryResult
|
||||
public interface UserQueryResultInterface {
|
||||
|
||||
@Property(name = "user.name")
|
||||
String getNameOfUser();
|
||||
@Property(name = "user.name")
|
||||
String getNameOfUser();
|
||||
|
||||
int getAgeOfUser();
|
||||
int getAgeOfUser();
|
||||
|
||||
User getUser();
|
||||
User getUser();
|
||||
|
||||
}
|
||||
|
||||
@@ -21,5 +21,4 @@ import org.springframework.stereotype.Repository;
|
||||
* @author Michal Bachman
|
||||
*/
|
||||
@Repository
|
||||
public interface AbstractAnnotatedEntityRepository extends Neo4jRepository<AbstractAnnotatedEntity, Long> {
|
||||
}
|
||||
public interface AbstractAnnotatedEntityRepository extends Neo4jRepository<AbstractAnnotatedEntity, Long> {}
|
||||
|
||||
@@ -21,5 +21,4 @@ import org.springframework.stereotype.Repository;
|
||||
* @author Michal Bachman
|
||||
*/
|
||||
@Repository
|
||||
public interface AbstractEntityRepository extends Neo4jRepository<AbstractEntity, Long> {
|
||||
}
|
||||
public interface AbstractEntityRepository extends Neo4jRepository<AbstractEntity, Long> {}
|
||||
|
||||
@@ -16,10 +16,7 @@ package org.springframework.data.neo4j.examples.movies.repo;
|
||||
import org.springframework.data.neo4j.examples.movies.domain.Actor;
|
||||
import org.springframework.data.neo4j.repository.Neo4jRepository;
|
||||
|
||||
|
||||
/**
|
||||
* @author Michal Bachman
|
||||
*/
|
||||
public interface ActorRepository extends Neo4jRepository<Actor, Long> {
|
||||
}
|
||||
|
||||
public interface ActorRepository extends Neo4jRepository<Actor, Long> {}
|
||||
|
||||
@@ -93,7 +93,8 @@ public interface CinemaRepository extends Neo4jRepository<Cinema, Long> {
|
||||
@Query(value = "MATCH (n:Theatre) RETURN n ORDER BY n.name", countQuery = "MATCH (n:Theatre) return count(*)")
|
||||
Page<Cinema> getPagedCinemasWithPageCount(Pageable pageable);
|
||||
|
||||
@Query(value = "MATCH (n:Theatre {city:{city}}) RETURN n ORDER BY n.name", countQuery = "MATCH (n:Theatre {city:{city}}) return count(*)")
|
||||
@Query(value = "MATCH (n:Theatre {city:{city}}) RETURN n ORDER BY n.name",
|
||||
countQuery = "MATCH (n:Theatre {city:{city}}) return count(*)")
|
||||
Page<Cinema> getPagedCinemasByCityWithPageCount(@Param("city") String city, Pageable pageable);
|
||||
|
||||
@Query("MATCH (n:Theatre) RETURN n")
|
||||
|
||||
@@ -21,5 +21,4 @@ import org.springframework.stereotype.Repository;
|
||||
* @author Michal Bachman
|
||||
*/
|
||||
@Repository
|
||||
public interface GenreRepository extends Neo4jRepository<Genre, Long> {
|
||||
}
|
||||
public interface GenreRepository extends Neo4jRepository<Genre, Long> {}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user