DATAGRAPH-1103 - 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.
# Conflicts:
# pom.xml
# spring-data-neo4j/pom.xml
This commit is contained in:
359
pom.xml
359
pom.xml
@@ -1,192 +1,193 @@
|
||||
<?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>5.0.9.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>5.0.9.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>2.0.9.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>2.0.9.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>
|
||||
<neo4j.ogm.version>3.0.4</neo4j.ogm.version>
|
||||
<springdata.commons>2.0.9.BUILD-SNAPSHOT</springdata.commons>
|
||||
<source.level>1.8</source.level>
|
||||
</properties>
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-neo4j</dist.id>
|
||||
<neo4j.ogm.version>3.0.4</neo4j.ogm.version>
|
||||
<springdata.commons>2.0.9.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>
|
||||
|
||||
<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,189 +12,190 @@
|
||||
~
|
||||
-->
|
||||
|
||||
<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>5.0.9.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>5.0.9.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<ogm.properties>ogm-bolt.properties</ogm.properties>
|
||||
<el-api.version>2.2</el-api.version>
|
||||
<java-module-name>spring.data.neo4j</java-module-name>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
</properties>
|
||||
<properties>
|
||||
<ogm.properties>ogm-bolt.properties</ogm.properties>
|
||||
<el-api.version>2.2</el-api.version>
|
||||
<java-module-name>spring.data.neo4j</java-module-name>
|
||||
<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 order required to build against CDI 1.0 and test with CDI 2.0 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-jcdi_2.0_spec</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- CDI -->
|
||||
<!-- Dependency order required to build against CDI 1.0 and test with CDI 2.0 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-jcdi_2.0_spec</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.interceptor</groupId>
|
||||
<artifactId>javax.interceptor-api</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.interceptor</groupId>
|
||||
<artifactId>javax.interceptor-api</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.enterprise</groupId>
|
||||
<artifactId>cdi-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.enterprise</groupId>
|
||||
<artifactId>cdi-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>${javax-annotation-api}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>${javax-annotation-api}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
<artifactId>openwebbeans-se</artifactId>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
<artifactId>openwebbeans-se</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>
|
||||
<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>
|
||||
|
||||
<!-- Cache -->
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>2.5.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- Cache -->
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>2.5.2</version>
|
||||
<optional>true</optional>
|
||||
</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-bolt-driver</artifactId>
|
||||
<version>${neo4j.ogm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-bolt-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>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson}</version>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
</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,19 +13,22 @@
|
||||
|
||||
package org.springframework.data.neo4j.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;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.neo4j.bookmark.BookmarkManagementConfiguration;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Enables bookmark management
|
||||
* <p>
|
||||
* Bean implementing {@link org.springframework.data.neo4j.bookmark.BookmarkManager} interface needs to exist in the
|
||||
* context. Default implementation {@link org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager} exists.
|
||||
* Use scope of the bean to control how bookmarks are managed.
|
||||
* singleton - suitable for application wide bookmarks, e.g. fat clients
|
||||
* request,session - suitable for web applications
|
||||
* context. Default implementation {@link org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager} exists. Use
|
||||
* scope of the bean to control how bookmarks are managed. singleton - suitable for application wide bookmarks, e.g. fat
|
||||
* clients request,session - suitable for web applications
|
||||
* <p>
|
||||
* NOTE: Only usable with OGM Bolt driver.
|
||||
*
|
||||
|
||||
@@ -13,13 +13,18 @@
|
||||
|
||||
package org.springframework.data.neo4j.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.springframework.context.annotation.Import;
|
||||
import org.springframework.data.auditing.DateTimeProvider;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.data.neo4j.repository.config.Neo4jAuditingRegistrar;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Annotation to enable auditing in MongoDB via annotation configuration.
|
||||
*
|
||||
|
||||
@@ -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,20 +13,23 @@
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Indicates that a transactional operation will use bookmarks that are currently stored in BookmarkManager when
|
||||
* creating Neo4j session.
|
||||
* Must be used on a method with @Transactional annotation.
|
||||
* May be used on class - applies to all methods or on specific methods.
|
||||
* creating Neo4j session. Must be used on a method with @Transactional annotation. May be used on class - applies to
|
||||
* all methods or on specific methods.
|
||||
* <p>
|
||||
*
|
||||
* @author Frantisek Hartman
|
||||
* @see EnableBookmarkManagement
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Documented
|
||||
public @interface UseBookmark {
|
||||
|
||||
|
||||
@@ -26,8 +26,7 @@ public class BookmarkInfo implements Serializable {
|
||||
private boolean useBookmark;
|
||||
private Collection<String> bookmarks;
|
||||
|
||||
public BookmarkInfo() {
|
||||
}
|
||||
public BookmarkInfo() {}
|
||||
|
||||
public BookmarkInfo(boolean useBookmark) {
|
||||
this.useBookmark = true;
|
||||
|
||||
@@ -21,16 +21,14 @@ import org.springframework.context.annotation.Role;
|
||||
/**
|
||||
* Configuration used by @{@link org.springframework.data.neo4j.annotation.EnableBookmarkManagement}
|
||||
* <p>
|
||||
* Note on bookmark management implementation:
|
||||
* The implementation closely follows implementation of @EnableTransactionManagement or @EnableCaching, with simplified
|
||||
* pointcut.
|
||||
* Note on bookmark management implementation: The implementation closely follows implementation
|
||||
* of @EnableTransactionManagement or @EnableCaching, with simplified pointcut.
|
||||
* <p>
|
||||
* The bookmark interceptor will set BookmarkInfo thread local when a methods is annotated with @UseBookmark.
|
||||
* It is executed before transactional advice (see setOrder(0) ).
|
||||
* Neo4j transaction manager then uses {@link BookmarkManager} bean to retrieve currently stored bookmarks and begins
|
||||
* new transaction using these bookmarks.
|
||||
* After commit new bookmark is stored in the BookmarkManager, replacing the bookmarks used to begin the transaction.
|
||||
* The user needs to provide the BookmarkManager bean.
|
||||
* The bookmark interceptor will set BookmarkInfo thread local when a methods is annotated with @UseBookmark. It is
|
||||
* executed before transactional advice (see setOrder(0) ). Neo4j transaction manager then uses {@link BookmarkManager}
|
||||
* bean to retrieve currently stored bookmarks and begins new transaction using these bookmarks. After commit new
|
||||
* bookmark is stored in the BookmarkManager, replacing the bookmarks used to begin the transaction. The user needs to
|
||||
* provide the BookmarkManager bean.
|
||||
*
|
||||
* @author Frantisek Hartman
|
||||
*/
|
||||
@@ -46,7 +44,6 @@ public class BookmarkManagementConfiguration {
|
||||
return advisor;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public BookmarkInterceptor bookmarkInterceptor() {
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
package org.springframework.data.neo4j.bookmark;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.support.StaticMethodMatcherPointcut;
|
||||
import org.springframework.data.neo4j.annotation.UseBookmark;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Pointcut for methods marked with @{@link UseBookmark}
|
||||
*
|
||||
@@ -33,7 +33,7 @@ public class BookmarkOperationPointcut extends StaticMethodMatcherPointcut {
|
||||
// method matches if @UseBookmark is on class, is true and not on method or
|
||||
// @UseBookmark is on method and is true
|
||||
// it is needed to cover @UseBookmark on class and @UseBookmark(false) on method
|
||||
return ((classAnnotation != null) && classAnnotation.value() && methodAnnotation == null) ||
|
||||
((methodAnnotation != null) && methodAnnotation.value());
|
||||
return ((classAnnotation != null) && classAnnotation.value() && methodAnnotation == null)
|
||||
|| ((methodAnnotation != null) && methodAnnotation.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
|
||||
package org.springframework.data.neo4j.bookmark;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
/**
|
||||
* Implementation of the bookmark manager using Caffeine cache
|
||||
* <p>
|
||||
@@ -32,10 +32,7 @@ public class CaffeineBookmarkManager implements BookmarkManager {
|
||||
private final Cache<String, String> cache;
|
||||
|
||||
public CaffeineBookmarkManager() {
|
||||
cache = Caffeine.newBuilder()
|
||||
.maximumSize(10_000)
|
||||
.expireAfterWrite(1, TimeUnit.MINUTES)
|
||||
.build();
|
||||
cache = Caffeine.newBuilder().maximumSize(10_000).expireAfterWrite(1, TimeUnit.MINUTES).build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,23 +13,22 @@
|
||||
|
||||
package org.springframework.data.neo4j.conversion;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
|
||||
import org.neo4j.ogm.metadata.ClassInfo;
|
||||
import org.neo4j.ogm.metadata.FieldInfo;
|
||||
import org.neo4j.ogm.metadata.MetaData;
|
||||
import org.neo4j.ogm.metadata.MethodInfo;
|
||||
import org.neo4j.ogm.typeconversion.AttributeConverter;
|
||||
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,80 +36,77 @@ 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ClassInfo classInfo : metaData.persistentEntities()) {
|
||||
for (FieldInfo fieldInfo : classInfo.propertyFields()) {
|
||||
if (fieldInfo.hasPropertyConverter()) {
|
||||
addWrappedConverter(fieldInfo.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,10 +12,14 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.mapping;
|
||||
|
||||
import static java.util.Collections.*;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.neo4j.ogm.annotation.typeconversion.Convert;
|
||||
import org.neo4j.ogm.metadata.MetaData;
|
||||
import org.neo4j.ogm.metadata.ClassInfo;
|
||||
import org.neo4j.ogm.metadata.FieldInfo;
|
||||
import org.neo4j.ogm.metadata.MetaData;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
@@ -23,18 +27,10 @@ import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
|
||||
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
|
||||
@@ -43,80 +39,84 @@ 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;
|
||||
metaData.persistentEntities().stream().filter(k -> k.getUnderlyingClass() != null).forEach(k -> addPersistentEntity(k.getUnderlyingClass()));
|
||||
logger.info("Neo4jMappingContext initialisation completed");
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
metaData.persistentEntities().stream().filter(k -> k.getUnderlyingClass() != null)
|
||||
.forEach(k -> addPersistentEntity(k.getUnderlyingClass()));
|
||||
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(Property property, Neo4jPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
@Override
|
||||
protected Neo4jPersistentProperty createPersistentProperty(Property property, Neo4jPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
ClassInfo owningClassInfo = this.metaData.classInfo(owner.getType().getName());
|
||||
ClassInfo owningClassInfo = this.metaData.classInfo(owner.getType().getName());
|
||||
|
||||
Field propertyField = property.getField().orElse(null);
|
||||
Field propertyField = property.getField().orElse(null);
|
||||
|
||||
if (!property.isFieldBacked() && owningClassInfo != null) {
|
||||
FieldInfo fieldInfo = owningClassInfo.propertyFieldByName(property.getName());
|
||||
if (fieldInfo == null) {
|
||||
fieldInfo = owningClassInfo.relationshipFieldByName(property.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 {} ",
|
||||
property.getName(), owningClassInfo.name());
|
||||
}
|
||||
}
|
||||
if (!property.isFieldBacked() && owningClassInfo != null) {
|
||||
FieldInfo fieldInfo = owningClassInfo.propertyFieldByName(property.getName());
|
||||
if (fieldInfo == null) {
|
||||
fieldInfo = owningClassInfo.relationshipFieldByName(property.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 {} ", property.getName(),
|
||||
owningClassInfo.name());
|
||||
}
|
||||
}
|
||||
|
||||
return new Neo4jPersistentProperty(owningClassInfo, property, owner,
|
||||
updateSimpleTypeHolder(simpleTypeHolder, propertyField));
|
||||
}
|
||||
return new Neo4jPersistentProperty(owningClassInfo, property, 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.mapping;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
@@ -21,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
|
||||
@@ -45,33 +41,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,11 +27,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>
|
||||
@@ -42,8 +41,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
|
||||
@@ -58,46 +57,51 @@ public class Neo4jPersistentProperty extends AnnotationBasedPersistentProperty<N
|
||||
|
||||
private final boolean isIdProperty;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Neo4jPersistentProperty} based on the given arguments.
|
||||
*
|
||||
* @param owningClassInfo The {@link ClassInfo} of the object of which the property field is a member
|
||||
* @param property The property
|
||||
* @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
|
||||
*/
|
||||
public Neo4jPersistentProperty(ClassInfo owningClassInfo, Property property,
|
||||
PersistentEntity<?, Neo4jPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
super(property, owner, simpleTypeHolder);
|
||||
if (owningClassInfo == null) {
|
||||
logger.warn("Owning ClassInfo is null for property: {}", property);
|
||||
}
|
||||
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, property);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Constructs a new {@link Neo4jPersistentProperty} based on the given arguments.
|
||||
*
|
||||
* @param owningClassInfo The {@link ClassInfo} of the object of which the property field is a member
|
||||
* @param property The property
|
||||
* @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
|
||||
*/
|
||||
public Neo4jPersistentProperty(ClassInfo owningClassInfo, Property property,
|
||||
PersistentEntity<?, Neo4jPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
super(property, owner, simpleTypeHolder);
|
||||
if (owningClassInfo == null) {
|
||||
logger.warn("Owning ClassInfo is null for property: {}", property);
|
||||
}
|
||||
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, property);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean resolveWhetherIdProperty(ClassInfo owningClassInfo, Property property) {
|
||||
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 {
|
||||
try {
|
||||
return property.getField() //
|
||||
.filter(field ->owningClassInfo.getField(owningClassInfo.identityField()).equals(field)) //
|
||||
.isPresent();}
|
||||
catch (MetadataException noIdentityField) {
|
||||
logger.warn("No identity field found for class of type: {} when creating persistent property for : {}",
|
||||
owningClassInfo.name(), property);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static boolean resolveWhetherIdProperty(ClassInfo owningClassInfo, Property property) {
|
||||
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 {
|
||||
try {
|
||||
return property.getField() //
|
||||
.filter(field -> owningClassInfo.getField(owningClassInfo.identityField()).equals(field)) //
|
||||
.isPresent();
|
||||
} catch (MetadataException noIdentityField) {
|
||||
logger.warn("No identity field found for class of type: {} when creating persistent property for : {}",
|
||||
owningClassInfo.name(), property);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdProperty() {
|
||||
@@ -123,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>
|
||||
@@ -133,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
|
||||
|
||||
@@ -57,7 +57,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
|
||||
@@ -66,7 +67,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,17 +16,18 @@
|
||||
|
||||
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.Optional;
|
||||
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.Optional;
|
||||
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.
|
||||
@@ -35,33 +36,34 @@ 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, Optional<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, Optional<CustomRepositoryImplementationDetector> detector) {
|
||||
super(qualifiers, repositoryType, beanManager, detector);
|
||||
this.sessionBean = sessionBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Optional<Object> customImplementation) {
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType,
|
||||
Optional<Object> customImplementation) {
|
||||
|
||||
Session session = getDependencyInstance(sessionBean, Session.class);
|
||||
Session session = getDependencyInstance(sessionBean, Session.class);
|
||||
|
||||
Neo4jRepositoryFactory factory = new Neo4jRepositoryFactory(session);
|
||||
Neo4jRepositoryFactory factory = new Neo4jRepositoryFactory(session);
|
||||
|
||||
return customImplementation //
|
||||
.map(impl -> factory.getRepository(repositoryType, impl)) //
|
||||
.orElseGet(() -> factory.getRepository(repositoryType));
|
||||
}
|
||||
return customImplementation //
|
||||
.map(impl -> factory.getRepository(repositoryType, impl)) //
|
||||
.orElseGet(() -> factory.getRepository(repositoryType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -37,6 +25,19 @@ import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
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.
|
||||
*
|
||||
@@ -45,68 +46,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,
|
||||
Optional.of(getCustomImplementationDetector()));
|
||||
}
|
||||
return new Neo4jCdiRepositoryBean<T>(sessionBean, qualifiers, repositoryType, beanManager,
|
||||
Optional.of(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;
|
||||
}
|
||||
|
||||
@@ -35,11 +35,11 @@ public class Neo4jAuditingEventListener extends EventListenerAdapter implements
|
||||
* Creates a new {@link Neo4jAuditingEventListener} using the given {@link MappingContext} and {@link AuditingHandler}
|
||||
* provided by the given {@link ObjectFactory}. This constructor does an additional registration to the
|
||||
* {@link SessionFactory}. Therefore the {@link SessionFactory} must already be instantiated.
|
||||
*
|
||||
*
|
||||
* @param auditingHandlerFactory must not be {@literal null}.
|
||||
*/
|
||||
public Neo4jAuditingEventListener(ObjectFactory<IsNewAwareAuditingHandler> auditingHandlerFactory,
|
||||
SessionFactory sessionFactory) {
|
||||
SessionFactory sessionFactory) {
|
||||
|
||||
Assert.notNull(auditingHandlerFactory, "IsNewAwareAuditingHandler must not be null!");
|
||||
this.auditingHandlerFactory = auditingHandlerFactory;
|
||||
@@ -50,7 +50,7 @@ public class Neo4jAuditingEventListener extends EventListenerAdapter implements
|
||||
/**
|
||||
* Constructor used for creating an instance in the {@link Neo4jAuditingRegistrar} to get registered in the session
|
||||
* "manually". The registration is done within the {@link Neo4jAuditingBeanFactoryPostProcessor}.
|
||||
*
|
||||
*
|
||||
* @param auditingHandlerFactory {@link AuditingHandler} to hook into the {@code preSave} phase for auditing.
|
||||
*/
|
||||
public Neo4jAuditingEventListener(ObjectFactory<IsNewAwareAuditingHandler> auditingHandlerFactory) {
|
||||
|
||||
@@ -47,7 +47,8 @@ public class Neo4jAuditingRegistrar extends AuditingBeanDefinitionRegistrarSuppo
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Neo4jIsNewAwareAuditingHandler.class);
|
||||
|
||||
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(Neo4jMappingContextFactoryBean.class);
|
||||
BeanDefinitionBuilder definition = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(Neo4jMappingContextFactoryBean.class);
|
||||
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
|
||||
builder.addConstructorArgValue(definition.getBeanDefinition());
|
||||
@@ -56,7 +57,7 @@ public class Neo4jAuditingRegistrar extends AuditingBeanDefinitionRegistrarSuppo
|
||||
|
||||
@Override
|
||||
protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition,
|
||||
BeanDefinitionRegistry registry) {
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null!");
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
|
||||
|
||||
@@ -33,7 +33,8 @@ public class Neo4jIsNewAwareAuditingHandler extends IsNewAwareAuditingHandler {
|
||||
|
||||
private IsNewStrategyFactory isNewStrategyFactory;
|
||||
|
||||
public Neo4jIsNewAwareAuditingHandler(MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> mappingContext) {
|
||||
public Neo4jIsNewAwareAuditingHandler(
|
||||
MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> mappingContext) {
|
||||
this(new PersistentEntities(Collections.singletonList(mappingContext)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -86,6 +86,7 @@ public abstract class AbstractGraphRepositoryQuery implements RepositoryQuery {
|
||||
|
||||
/**
|
||||
* Does the query returns an OGM specific object type that should get a special processing ?
|
||||
*
|
||||
* @return true is that's the case
|
||||
*/
|
||||
private boolean returnsOgmSpecificType() {
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.springframework.data.neo4j.annotation.QueryResult;
|
||||
*/
|
||||
class CustomResultConverter implements Converter<Object, Object> {
|
||||
|
||||
|
||||
private final MetaData metaData;
|
||||
private final Class returnedType;
|
||||
|
||||
@@ -48,8 +47,9 @@ class CustomResultConverter implements Converter<Object, Object> {
|
||||
}
|
||||
SingleUseEntityMapper mapper = new SingleUseEntityMapper(metaData, new EntityFactory(metaData));
|
||||
if (returnedType.isInterface()) {
|
||||
Class<?>[] interfaces = new Class<?>[]{returnedType};
|
||||
return newProxyInstance(returnedType.getClassLoader(), interfaces, new QueryResultProxy((Map<String, Object>) source));
|
||||
Class<?>[] interfaces = new Class<?>[] { returnedType };
|
||||
return newProxyInstance(returnedType.getClassLoader(), interfaces,
|
||||
new QueryResultProxy((Map<String, Object>) source));
|
||||
}
|
||||
return mapper.map(returnedType, (Map<String, Object>) source);
|
||||
}
|
||||
|
||||
@@ -24,13 +24,16 @@ import org.springframework.data.repository.query.ParameterAccessor;
|
||||
public interface GraphParameterAccessor extends ParameterAccessor {
|
||||
|
||||
/**
|
||||
* Gets the loading depth value of the {@link org.springframework.data.neo4j.annotation.Depth} annotated method parameter.
|
||||
* Gets the loading depth value of the {@link org.springframework.data.neo4j.annotation.Depth} annotated method
|
||||
* parameter.
|
||||
*
|
||||
* @return the depth value
|
||||
*/
|
||||
int getDepth();
|
||||
|
||||
/**
|
||||
* Get OGM specific sort order translated from method parameters.
|
||||
*
|
||||
* @return The sort order
|
||||
*/
|
||||
SortOrder getOgmSort();
|
||||
|
||||
@@ -61,8 +61,8 @@ public class GraphParameters extends Parameters<GraphParameters, GraphParameters
|
||||
if (this.depthIndex == null && graphParameter.isDepthParameter()) {
|
||||
this.depthIndex = graphParameter.getIndex();
|
||||
} else if (graphParameter.isDepthParameter()) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Found multiple @Depth annotations on method %s! Only one allowed!", parameter.getMethod().toString()));
|
||||
throw new IllegalStateException(String.format("Found multiple @Depth annotations on method %s! Only one allowed!",
|
||||
parameter.getMethod().toString()));
|
||||
}
|
||||
|
||||
return graphParameter;
|
||||
@@ -98,8 +98,8 @@ public class GraphParameters extends Parameters<GraphParameters, GraphParameters
|
||||
@Override
|
||||
public boolean isSpecialParameter() {
|
||||
return super.isSpecialParameter() || Distance.class.isAssignableFrom(getType())
|
||||
|| parameter.getParameterAnnotation(Depth.class) != null
|
||||
|| Distance.class.isAssignableFrom(getType()) || Point.class.isAssignableFrom(getType());
|
||||
|| parameter.getParameterAnnotation(Depth.class) != null || Distance.class.isAssignableFrom(getType())
|
||||
|| Point.class.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
boolean isDepthParameter() {
|
||||
|
||||
@@ -32,7 +32,8 @@ public class GraphParametersParameterAccessor extends ParametersParameterAccesso
|
||||
|
||||
/**
|
||||
* Creates a new {@link ParametersParameterAccessor}.
|
||||
* @param method must not be {@literal null}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param values must not be {@literal null}.
|
||||
*/
|
||||
public GraphParametersParameterAccessor(GraphQueryMethod method, Object[] values) {
|
||||
|
||||
@@ -40,10 +40,10 @@ import org.springframework.data.repository.support.PageableExecutionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Classes intended to pilot query execution according to the type of the query.
|
||||
* The type of the query is determined by looking at the result class of the method.
|
||||
* @see AbstractGraphRepositoryQuery#getExecution(org.springframework.data.neo4j.repository.query.GraphParameterAccessor)
|
||||
* Classes intended to pilot query execution according to the type of the query. The type of the query is determined by
|
||||
* looking at the result class of the method.
|
||||
*
|
||||
* @see AbstractGraphRepositoryQuery#getExecution(org.springframework.data.neo4j.repository.query.GraphParameterAccessor)
|
||||
* @author Nicolas Mervaillie
|
||||
*/
|
||||
public interface GraphQueryExecution {
|
||||
@@ -75,7 +75,7 @@ public interface GraphQueryExecution {
|
||||
}
|
||||
}
|
||||
Iterator<?> iterator = result.iterator();
|
||||
if (! iterator.hasNext()) {
|
||||
if (!iterator.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
Object ret = iterator.next();
|
||||
@@ -144,9 +144,9 @@ public interface GraphQueryExecution {
|
||||
List<?> result;
|
||||
long count;
|
||||
if (query.isFilterQuery()) {
|
||||
result = (List<?>) session.loadAll(type, query.getFilters(), accessor.getOgmSort()
|
||||
, query.getPagination(pageable, false), accessor.getDepth());
|
||||
count = session.count(type, query.getFilters());
|
||||
result = (List<?>) session.loadAll(type, query.getFilters(), accessor.getOgmSort(),
|
||||
query.getPagination(pageable, false), accessor.getDepth());
|
||||
count = session.count(type, query.getFilters());
|
||||
} else {
|
||||
if (type.getAnnotation(QueryResult.class) != null) {
|
||||
result = (List<?>) session.query(query.getCypherQuery(pageable, false), query.getParameters()).queryResults();
|
||||
@@ -185,8 +185,8 @@ public interface GraphQueryExecution {
|
||||
List<?> result;
|
||||
if (query.isFilterQuery()) {
|
||||
// For a slice, need one extra result to determine if there is a next page
|
||||
result = (List<?>) session.loadAll(type, query.getFilters(), accessor.getOgmSort()
|
||||
, query.getPagination(pageable, true), accessor.getDepth());
|
||||
result = (List<?>) session.loadAll(type, query.getFilters(), accessor.getOgmSort(),
|
||||
query.getPagination(pageable, true), accessor.getDepth());
|
||||
} else {
|
||||
String cypherQuery = query.getCypherQuery(pageable, true);
|
||||
if (type.getAnnotation(QueryResult.class) != null) {
|
||||
|
||||
@@ -33,107 +33,106 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class GraphQueryMethod extends QueryMethod {
|
||||
|
||||
private final Method method;
|
||||
private final Query queryAnnotation;
|
||||
private final Integer queryDepthParamIndex;
|
||||
private final Method method;
|
||||
private final Query queryAnnotation;
|
||||
private final Integer queryDepthParamIndex;
|
||||
|
||||
public GraphQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
|
||||
super(method, metadata, factory);
|
||||
this.method = method;
|
||||
this.queryAnnotation = method.getAnnotation(Query.class);
|
||||
this.queryDepthParamIndex = getQueryDepthParamIndex(method);
|
||||
Integer 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) {
|
||||
super(method, metadata, factory);
|
||||
this.method = method;
|
||||
this.queryAnnotation = method.getAnnotation(Query.class);
|
||||
this.queryDepthParamIndex = getQueryDepthParamIndex(method);
|
||||
Integer queryDepth = getStaticQueryDepth(method);
|
||||
if (queryDepth != null && queryDepthParamIndex != null) {
|
||||
throw new IllegalArgumentException(method.getName() + " cannot have both a method @Depth and a parameter @Depth");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parameters<?, ?> createParameters(Method method) {
|
||||
return new GraphParameters(method);
|
||||
}
|
||||
@Override
|
||||
protected Parameters<?, ?> createParameters(Method method) {
|
||||
return new GraphParameters(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphParameters getParameters() {
|
||||
return (GraphParameters) super.getParameters();
|
||||
}
|
||||
@Override
|
||||
public GraphParameters getParameters() {
|
||||
return (GraphParameters) super.getParameters();
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return queryAnnotation.value();
|
||||
}
|
||||
public String getQuery() {
|
||||
return queryAnnotation.value();
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the named query this method belongs to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getNamedQueryName() {
|
||||
return String.format("%s.%s", getDomainClass().getSimpleName(), method.getName());
|
||||
}
|
||||
/**
|
||||
* Returns the name of the named query this method belongs to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getNamedQueryName() {
|
||||
return String.format("%s.%s", getDomainClass().getSimpleName(), method.getName());
|
||||
}
|
||||
|
||||
public Integer getQueryDepthParamIndex() {
|
||||
return queryDepthParamIndex;
|
||||
}
|
||||
public Integer getQueryDepthParamIndex() {
|
||||
return queryDepthParamIndex;
|
||||
}
|
||||
|
||||
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)) {
|
||||
return method.getAnnotation(Depth.class).value();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private Integer getStaticQueryDepth(Method method) {
|
||||
if (method.isAnnotationPresent(Depth.class)) {
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean hasAnnotatedQuery() {
|
||||
return getAnnotatedQuery() != null;
|
||||
}
|
||||
public boolean hasAnnotatedQuery() {
|
||||
return getAnnotatedQuery() != null;
|
||||
}
|
||||
|
||||
private String getAnnotatedQuery() {
|
||||
private String getAnnotatedQuery() {
|
||||
|
||||
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
|
||||
return StringUtils.hasText(query) ? query : null;
|
||||
}
|
||||
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
|
||||
return StringUtils.hasText(query) ? query : null;
|
||||
}
|
||||
|
||||
private Query getQueryAnnotation() {
|
||||
return AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
|
||||
}
|
||||
private Query getQueryAnnotation() {
|
||||
return AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.query;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -40,7 +39,6 @@ import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
|
||||
|
||||
/**
|
||||
* Specialisation of {@link RepositoryQuery} that handles mapping to object annotated with <code>@Query</code>.
|
||||
*
|
||||
@@ -76,8 +74,9 @@ public class GraphRepositoryQuery extends AbstractGraphRepositoryQuery {
|
||||
|
||||
Object result = getExecution(accessor).execute(query, processor.getReturnedType().getReturnedType());
|
||||
|
||||
return Result.class.equals(returnType)
|
||||
? result : processor.processResult(result, new CustomResultConverter(getMetaData(), processor.getReturnedType().getReturnedType()));
|
||||
return Result.class.equals(returnType) ? result
|
||||
: processor.processResult(result,
|
||||
new CustomResultConverter(getMetaData(), processor.getReturnedType().getReturnedType()));
|
||||
}
|
||||
|
||||
protected Query getQuery(Object[] parameters) {
|
||||
@@ -113,9 +112,9 @@ public class GraphRepositoryQuery extends AbstractGraphRepositoryQuery {
|
||||
|
||||
private Object getParameterValue(Object parameter) {
|
||||
|
||||
//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(parameter);
|
||||
if (parameterValue == null) { //Either not an entity or not persisted
|
||||
if (parameterValue == null) { // Either not an entity or not persisted
|
||||
parameterValue = parameter;
|
||||
}
|
||||
return parameterValue;
|
||||
|
||||
@@ -37,9 +37,8 @@ import org.springframework.data.neo4j.util.PagingAndSortingUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents an OGM query. Can hold either cypher queries or filter definitions.
|
||||
* Also in charge of adding pagination / sort to the string based queries as OGM does not support
|
||||
* pagination and sort on those.
|
||||
* Represents an OGM query. Can hold either cypher queries or filter definitions. Also in charge of adding pagination /
|
||||
* sort to the string based queries as OGM does not support pagination and sort on those.
|
||||
*
|
||||
* @author Nicolas Mervaillie
|
||||
*/
|
||||
@@ -102,7 +101,7 @@ public class Query {
|
||||
sort = pageable.getSort();
|
||||
}
|
||||
if (sort != Sort.unsorted()) {
|
||||
//Custom queries in the OGM do not support pageable
|
||||
// Custom queries in the OGM do not support pageable
|
||||
result = addSorting(result, sort);
|
||||
}
|
||||
result = addPaging(result, pageable, forSlicing);
|
||||
@@ -110,7 +109,7 @@ public class Query {
|
||||
}
|
||||
|
||||
public String getCypherQuery(Sort sort) {
|
||||
//Custom queries in the OGM do not support pageable
|
||||
// Custom queries in the OGM do not support pageable
|
||||
String result = cypherQuery;
|
||||
if (sort != Sort.unsorted()) {
|
||||
result = addSorting(cypherQuery, sort);
|
||||
@@ -119,7 +118,7 @@ public class Query {
|
||||
}
|
||||
|
||||
private String addPaging(String cypherQuery, Pageable pageable, boolean forSlicing) {
|
||||
//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;
|
||||
parameters.put(SKIP, pageable.getPageNumber() * pageable.getPageSize());
|
||||
@@ -163,7 +162,7 @@ public class Query {
|
||||
}
|
||||
|
||||
public Pagination getPagination(Pageable pageable, boolean forSlicing) {
|
||||
Pagination pagination = new Pagination(pageable.getPageNumber(), pageable.getPageSize() + ((forSlicing)?1:0));
|
||||
Pagination pagination = new Pagination(pageable.getPageNumber(), pageable.getPageSize() + ((forSlicing) ? 1 : 0));
|
||||
pagination.setOffset(pageable.getPageNumber() * pageable.getPageSize());
|
||||
return pagination;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,8 @@ public class DerivedGraphRepositoryQuery extends AbstractGraphRepositoryQuery {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -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(distanceComparison, ComparisonOperator.LESS_THAN);
|
||||
|
||||
@@ -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,19 +30,19 @@ 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(propertyName(), ComparisonOperator.IS_NULL);
|
||||
filter.setOwnerEntityType(entityType);
|
||||
filter.setBooleanOperator(booleanOperator);
|
||||
filter.setNegated(isNegated() || part.getType() == IS_NOT_NULL);
|
||||
setNestedAttributes(part, filter);
|
||||
@Override
|
||||
public List<Filter> build(Stack<Object> params) {
|
||||
Filter filter = new Filter(propertyName(), ComparisonOperator.IS_NULL);
|
||||
filter.setOwnerEntityType(entityType);
|
||||
filter.setBooleanOperator(booleanOperator);
|
||||
filter.setNegated(isNegated() || part.getType() == IS_NOT_NULL);
|
||||
setNestedAttributes(part, filter);
|
||||
|
||||
return Collections.singletonList(filter);
|
||||
}
|
||||
return Collections.singletonList(filter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ public class PropertyComparisonBuilder extends FilterBuilder {
|
||||
return Collections.singletonList(filter);
|
||||
}
|
||||
|
||||
|
||||
private ComparisonOperator convertToComparisonOperator(Part.Type type) {
|
||||
switch (type) {
|
||||
case AFTER:
|
||||
|
||||
@@ -13,55 +13,52 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.support;
|
||||
|
||||
import org.neo4j.ogm.metadata.MetaData;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.neo4j.ogm.metadata.ClassInfo;
|
||||
import org.neo4j.ogm.metadata.FieldInfo;
|
||||
import org.neo4j.ogm.metadata.reflect.EntityAccessManager;
|
||||
import org.neo4j.ogm.metadata.MetaData;
|
||||
import org.springframework.data.repository.core.support.AbstractEntityInformation;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Mark Angrish
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
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
|
||||
@SuppressWarnings("unchecked")
|
||||
public ID getId(T entity) {
|
||||
final ClassInfo classInfo = metaData.classInfo(getJavaType().getName());
|
||||
final FieldInfo primaryIndex = classInfo.primaryIndexField();
|
||||
public ID getId(T entity) {
|
||||
final ClassInfo classInfo = metaData.classInfo(getJavaType().getName());
|
||||
final FieldInfo primaryIndex = classInfo.primaryIndexField();
|
||||
|
||||
return (ID) getId(entity, classInfo, primaryIndex);
|
||||
}
|
||||
return (ID) getId(entity, classInfo, primaryIndex);
|
||||
}
|
||||
|
||||
private Object getId(T entity, ClassInfo classInfo, FieldInfo primaryIndex) {
|
||||
if (primaryIndex != null) {
|
||||
return classInfo.propertyField(primaryIndex.getName()).readProperty(entity);
|
||||
}
|
||||
else {
|
||||
return classInfo.propertyField(classInfo.identityField().getName()).readProperty(entity);
|
||||
}
|
||||
}
|
||||
private Object getId(T entity, ClassInfo classInfo, FieldInfo primaryIndex) {
|
||||
if (primaryIndex != null) {
|
||||
return classInfo.propertyField(primaryIndex.getName()).readProperty(entity);
|
||||
} else {
|
||||
return classInfo.propertyField(classInfo.identityField().getName()).readProperty(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<ID> getIdType() {
|
||||
final FieldInfo primaryIndex = metaData.classInfo(getJavaType().getName()).primaryIndexField();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.neo4j.ogm.session.Neo4jSession;
|
||||
@@ -58,7 +57,7 @@ public class Neo4jRepositoryFactory extends RepositoryFactorySupport {
|
||||
public <T, ID> 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
|
||||
@@ -73,7 +72,7 @@ public class Neo4jRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
@Override
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key,
|
||||
EvaluationContextProvider evaluationContextProvider) {
|
||||
EvaluationContextProvider evaluationContextProvider) {
|
||||
return Optional.of(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,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
|
||||
@@ -190,8 +189,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, PagingAndSortingUtils.convert(pageable.getSort())
|
||||
, new Pagination(pageable.getPageNumber(), pageable.getPageSize()), depth);
|
||||
Collection<T> data = session.loadAll(clazz, PagingAndSortingUtils.convert(pageable.getSort()),
|
||||
new Pagination(pageable.getPageNumber(), pageable.getPageSize()), depth);
|
||||
return updatePage(pageable, new ArrayList<>(data));
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.transaction;
|
||||
|
||||
|
||||
import static java.util.Collections.*;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -44,24 +43,22 @@ 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 static final Logger logger = LoggerFactory.getLogger(Neo4jTransactionManager.class);
|
||||
|
||||
@@ -70,7 +67,8 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
@@ -78,7 +76,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
setTransactionSynchronization(SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Neo4jTransactionManager instance.
|
||||
*
|
||||
@@ -89,17 +86,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.
|
||||
*/
|
||||
@@ -107,7 +103,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a default SessionFactory bean.
|
||||
*/
|
||||
@@ -124,7 +119,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (getSessionFactory() == null) {
|
||||
@@ -132,13 +126,11 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getResourceFactory() {
|
||||
return getSessionFactory();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() {
|
||||
Neo4jTransactionObject txObject = new Neo4jTransactionObject();
|
||||
@@ -146,28 +138,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");
|
||||
@@ -184,8 +172,7 @@ 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.Type type = getTransactionType(definition, txObject);
|
||||
@@ -243,10 +230,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
|
||||
*/
|
||||
@@ -267,17 +252,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;
|
||||
@@ -286,11 +268,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) {
|
||||
|
||||
@@ -326,7 +306,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
Neo4jTransactionObject txObject = (Neo4jTransactionObject) status.getTransaction();
|
||||
@@ -352,18 +331,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;
|
||||
@@ -395,8 +372,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 {
|
||||
|
||||
@@ -406,8 +382,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;
|
||||
}
|
||||
@@ -435,8 +410,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 {
|
||||
|
||||
|
||||
@@ -46,10 +46,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
|
||||
*/
|
||||
@@ -57,9 +57,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 {
|
||||
|
||||
@@ -67,11 +65,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();
|
||||
}
|
||||
@@ -88,22 +86,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) {
|
||||
|
||||
@@ -160,9 +156,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;
|
||||
}
|
||||
}
|
||||
@@ -175,15 +173,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;
|
||||
}
|
||||
@@ -194,8 +189,7 @@ public class SessionFactoryUtils {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushResource(SessionHolder resourceHolder) {
|
||||
}
|
||||
public void flushResource(SessionHolder resourceHolder) {}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUnbindAtCompletion() {
|
||||
@@ -204,7 +198,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.core.NotFoundException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.neo4j.ogm.exception.core.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;
|
||||
|
||||
@@ -48,20 +48,19 @@ public class JavaConfigurationAuditingTests extends MultiDriverTestClass {
|
||||
@EnableNeo4jRepositories(basePackageClasses = UserRepository.class)
|
||||
static class Neo4jConfiguration {
|
||||
|
||||
|
||||
@Bean
|
||||
public SessionFactory sessionFactory() {
|
||||
return new SessionFactory(getBaseConfiguration().build(), User.class.getPackage().getName());
|
||||
return new SessionFactory(getBaseConfiguration().build(), User.class.getPackage().getName());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Neo4jTransactionManager transactionManager() {
|
||||
return new Neo4jTransactionManager();
|
||||
return new Neo4jTransactionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuditorAware<String> auditorAware() {
|
||||
return new AuditorAware<String>() {
|
||||
return new AuditorAware<String>() {
|
||||
|
||||
@Override
|
||||
public Optional<String> getCurrentAuditor() {
|
||||
@@ -71,8 +70,7 @@ public class JavaConfigurationAuditingTests extends MultiDriverTestClass {
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
@Autowired private UserRepository userRepository;
|
||||
|
||||
@Test
|
||||
public void whenSaveEntity_thenSetCreatedAndCreatedBy() throws Exception {
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
|
||||
package org.springframework.data.neo4j.auditing.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author Frantisek Hartman
|
||||
*/
|
||||
@@ -31,20 +31,15 @@ public class User {
|
||||
|
||||
String name;
|
||||
|
||||
@CreatedDate
|
||||
LocalDateTime created;
|
||||
@CreatedDate LocalDateTime created;
|
||||
|
||||
@CreatedBy
|
||||
String createdBy;
|
||||
@CreatedBy String createdBy;
|
||||
|
||||
@LastModifiedDate
|
||||
LocalDateTime modified;
|
||||
@LastModifiedDate LocalDateTime modified;
|
||||
|
||||
@LastModifiedBy
|
||||
String modifiedBy;
|
||||
@LastModifiedBy String modifiedBy;
|
||||
|
||||
public User() {
|
||||
}
|
||||
public User() {}
|
||||
|
||||
public User(String name) {
|
||||
this.name = name;
|
||||
|
||||
@@ -19,5 +19,4 @@ import org.springframework.data.neo4j.repository.Neo4jRepository;
|
||||
/**
|
||||
* @author Frantisek Hartman
|
||||
*/
|
||||
public interface UserRepository extends Neo4jRepository<User, Long> {
|
||||
}
|
||||
public interface UserRepository extends Neo4jRepository<User, Long> {}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package org.springframework.data.neo4j.bookmark;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -24,8 +26,6 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Frantisek Hartman
|
||||
*/
|
||||
@@ -33,11 +33,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ContextConfiguration(classes = BookmarkManagementTest.BookmarkManagementConfiguration.class)
|
||||
public class BookmarkManagementTest {
|
||||
|
||||
@Autowired
|
||||
private UseBookmarkOnMethodBean useBookmarkOnMethodBean;
|
||||
@Autowired private UseBookmarkOnMethodBean useBookmarkOnMethodBean;
|
||||
|
||||
@Autowired
|
||||
private UseBookmarkOnClassBean useBookmarkOnClassBean;
|
||||
@Autowired private UseBookmarkOnClassBean useBookmarkOnClassBean;
|
||||
|
||||
@Test
|
||||
public void givenUseBookmarkOnMethod_whenRun_thenShouldUseBookmarkIsSet() throws Exception {
|
||||
@@ -50,8 +48,7 @@ public class BookmarkManagementTest {
|
||||
|
||||
@Test
|
||||
public void givenUseBookmarkOnMethod_whenRun_thenRemoveBookmarkInfoAfterRun() throws Exception {
|
||||
useBookmarkOnMethodBean.runWithBookmark(() -> {
|
||||
});
|
||||
useBookmarkOnMethodBean.runWithBookmark(() -> {});
|
||||
|
||||
BookmarkInfo bookmarkInfo = BookmarkSupport.currentBookmarkInfo();
|
||||
assertThat(bookmarkInfo).isNull();
|
||||
@@ -84,8 +81,7 @@ public class BookmarkManagementTest {
|
||||
|
||||
@Test
|
||||
public void givenUseBookmarkOnClass_whenRun_thenRemoveBookmarkInfoAfterRun() throws Exception {
|
||||
useBookmarkOnClassBean.runWithBookmark(() -> {
|
||||
});
|
||||
useBookmarkOnClassBean.runWithBookmark(() -> {});
|
||||
|
||||
BookmarkInfo bookmarkInfo = BookmarkSupport.currentBookmarkInfo();
|
||||
assertThat(bookmarkInfo).isNull();
|
||||
@@ -134,5 +130,4 @@ public class BookmarkManagementTest {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Service
|
||||
public class FriendService {
|
||||
|
||||
@Autowired
|
||||
Session session;
|
||||
@Autowired Session session;
|
||||
|
||||
@Transactional
|
||||
public void createPersonAndFriends() {
|
||||
|
||||
@@ -16,10 +16,8 @@ package org.springframework.data.neo4j.examples.friends;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.ogm.cypher.ComparisonOperator;
|
||||
import org.neo4j.ogm.cypher.Filter;
|
||||
import org.neo4j.ogm.session.Session;
|
||||
@@ -44,16 +42,14 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
* @author Luanne Misquitta
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@ContextConfiguration(classes = {FriendTests.FriendContext.class})
|
||||
@ContextConfiguration(classes = { FriendTests.FriendContext.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class FriendTests extends MultiDriverTestClass {
|
||||
|
||||
|
||||
@Autowired Session session;
|
||||
@Autowired FriendshipRepository friendshipRepository;
|
||||
@Autowired FriendService friendService;
|
||||
|
||||
|
||||
@Before
|
||||
public void cleanUpDatabase() {
|
||||
getGraphDatabaseService().execute("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE r, n");
|
||||
@@ -68,7 +64,8 @@ public class FriendTests extends MultiDriverTestClass {
|
||||
friendService.createPersonAndFriends();
|
||||
|
||||
session.clear();
|
||||
Person john = session.loadAll(Person.class, new Filter("firstName", ComparisonOperator.EQUALS, "John")).iterator().next();
|
||||
Person john = session.loadAll(Person.class, new Filter("firstName", ComparisonOperator.EQUALS, "John")).iterator()
|
||||
.next();
|
||||
assertNotNull(john);
|
||||
assertEquals(2, john.getFriendships().size());
|
||||
}
|
||||
@@ -111,7 +108,8 @@ public class FriendTests extends MultiDriverTestClass {
|
||||
|
||||
@Bean
|
||||
public SessionFactory sessionFactory() {
|
||||
return new SessionFactory(getBaseConfiguration().build(), "org.springframework.data.neo4j.examples.friends.domain");
|
||||
return new SessionFactory(getBaseConfiguration().build(),
|
||||
"org.springframework.data.neo4j.examples.friends.domain");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
|
||||
@@ -49,18 +49,16 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* @author Vince Bickers
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ContextConfiguration(classes = {GalaxyServiceTests.GalaxyContext.class})
|
||||
@ContextConfiguration(classes = { GalaxyServiceTests.GalaxyContext.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@Transactional
|
||||
public class GalaxyServiceTests extends MultiDriverTestClass {
|
||||
|
||||
@Autowired
|
||||
private GalaxyService galaxyService;
|
||||
@Autowired private GalaxyService galaxyService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -108,7 +106,6 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldFindWorldsByName() {
|
||||
galaxyService.makeSomeWorlds();
|
||||
@@ -150,9 +147,7 @@ public class GalaxyServiceTests 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"))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,11 +216,11 @@ public class GalaxyServiceTests 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) {
|
||||
sum -= world.getId();
|
||||
@@ -251,7 +246,7 @@ public class GalaxyServiceTests 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());
|
||||
@@ -308,13 +303,13 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
|
||||
names.add(world.getName());
|
||||
}
|
||||
|
||||
String[] sortedNames = names.toArray(new String[]{});
|
||||
String[] sortedNames = names.toArray(new String[] {});
|
||||
Arrays.sort(sortedNames);
|
||||
return sortedNames;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan({"org.springframework.data.neo4j.examples.galaxy.service"})
|
||||
@ComponentScan({ "org.springframework.data.neo4j.examples.galaxy.service" })
|
||||
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.galaxy.repo")
|
||||
@EnableTransactionManagement
|
||||
static class GalaxyContext {
|
||||
@@ -326,7 +321,8 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
|
||||
|
||||
@Bean
|
||||
public SessionFactory sessionFactory() {
|
||||
return new SessionFactory(getBaseConfiguration().build(), "org.springframework.data.neo4j.examples.galaxy.domain");
|
||||
return new SessionFactory(getBaseConfiguration().build(),
|
||||
"org.springframework.data.neo4j.examples.galaxy.domain");
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -37,82 +37,81 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
@ContextConfiguration(classes = {WorldRepositoryTests.GalaxyContext.class})
|
||||
@ContextConfiguration(classes = { WorldRepositoryTests.GalaxyContext.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class WorldRepositoryTests extends MultiDriverTestClass {
|
||||
|
||||
@Autowired
|
||||
WorldRepository worldRepository;
|
||||
@Autowired WorldRepository worldRepository;
|
||||
|
||||
@Autowired
|
||||
TransactionTemplate transactionTemplate;
|
||||
@Autowired TransactionTemplate transactionTemplate;
|
||||
|
||||
boolean failed = false;
|
||||
boolean failed = false;
|
||||
|
||||
/**
|
||||
* see https://jira.spring.io/browse/DATAGRAPH-951
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void multipleThreadsResultsGetMixedUp() throws Exception {
|
||||
/**
|
||||
* 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;
|
||||
int iterations = 10;
|
||||
|
||||
ExecutorService service = Executors.newFixedThreadPool(2);
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(iterations * 2);
|
||||
ExecutorService service = Executors.newFixedThreadPool(2);
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(iterations * 2);
|
||||
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
|
||||
service.execute(() -> {
|
||||
World world = worldRepository.findByName("world 1");
|
||||
service.execute(() -> {
|
||||
World world = worldRepository.findByName("world 1");
|
||||
|
||||
if (!"world 1".equals(world.getName())) {
|
||||
failed = true;
|
||||
}
|
||||
countDownLatch.countDown();
|
||||
});
|
||||
if (!"world 1".equals(world.getName())) {
|
||||
failed = true;
|
||||
}
|
||||
countDownLatch.countDown();
|
||||
});
|
||||
|
||||
service.execute(() -> {
|
||||
service.execute(() -> {
|
||||
|
||||
World world = worldRepository.findByName("world 2");
|
||||
World world = worldRepository.findByName("world 2");
|
||||
|
||||
if (!"world 2".equals(world.getName())) {
|
||||
failed = true;
|
||||
}
|
||||
countDownLatch.countDown();
|
||||
});
|
||||
}
|
||||
countDownLatch.await();
|
||||
assertFalse(failed);
|
||||
}
|
||||
if (!"world 2".equals(world.getName())) {
|
||||
failed = true;
|
||||
}
|
||||
countDownLatch.countDown();
|
||||
});
|
||||
}
|
||||
countDownLatch.await();
|
||||
assertFalse(failed);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan({"org.springframework.data.neo4j.examples.galaxy.service"})
|
||||
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.galaxy.repo")
|
||||
@EnableTransactionManagement
|
||||
static class GalaxyContext {
|
||||
@Configuration
|
||||
@ComponentScan({ "org.springframework.data.neo4j.examples.galaxy.service" })
|
||||
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.galaxy.repo")
|
||||
@EnableTransactionManagement
|
||||
static class GalaxyContext {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return new Neo4jTransactionManager(sessionFactory());
|
||||
}
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return new Neo4jTransactionManager(sessionFactory());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SessionFactory sessionFactory() {
|
||||
return new SessionFactory(getBaseConfiguration().build(), "org.springframework.data.neo4j.examples.galaxy.domain");
|
||||
}
|
||||
@Bean
|
||||
public SessionFactory sessionFactory() {
|
||||
return new SessionFactory(getBaseConfiguration().build(),
|
||||
"org.springframework.data.neo4j.examples.galaxy.domain");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TransactionTemplate transactionTemplate() {
|
||||
return new TransactionTemplate(transactionManager());
|
||||
}
|
||||
@Bean
|
||||
public TransactionTemplate transactionTemplate() {
|
||||
return new TransactionTemplate(transactionManager());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,114 +13,117 @@
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Relationship(type=REACHABLE_BY_ROCKET, direction = "UNDIRECTED")
|
||||
private Set<World> reachableByRocket = new HashSet<>();
|
||||
@Relationship(type = REACHABLE_BY_ROCKET,
|
||||
direction = "UNDIRECTED") 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.
|
||||
}
|
||||
|
||||
public Set<World> getReachableByRocket() {
|
||||
return this.reachableByRocket;
|
||||
}
|
||||
public Set<World> getReachableByRocket() {
|
||||
return this.reachableByRocket;
|
||||
}
|
||||
|
||||
public void setReachableByRocket(Set<World> reachableByRocket) {
|
||||
this.reachableByRocket.clear();
|
||||
this.reachableByRocket = reachableByRocket;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@ import org.springframework.stereotype.Repository;
|
||||
@Repository
|
||||
public interface WorldRepository extends Neo4jRepository<World, Long> {
|
||||
|
||||
@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);
|
||||
|
||||
}
|
||||
|
||||
@@ -40,11 +40,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();
|
||||
@@ -93,13 +91,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);
|
||||
@@ -167,7 +165,6 @@ public class GalaxyService {
|
||||
return session.loadAll(World.class, new Filter(propertyName, ComparisonOperator.EQUALS, propertyValue), depth);
|
||||
}
|
||||
|
||||
|
||||
public Iterable<World> findAllWorlds(Pagination paging) {
|
||||
return session.loadAll(World.class, paging, 0);
|
||||
}
|
||||
|
||||
@@ -43,18 +43,16 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
* @author Vince Bickers
|
||||
* @author Mark Angrish
|
||||
*/
|
||||
@ContextConfiguration(classes = {WebConfiguration.class, JSR303Tests.JSR303Context.class})
|
||||
@ContextConfiguration(classes = { WebConfiguration.class, JSR303Tests.JSR303Context.class })
|
||||
@WebAppConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class JSR303Tests 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;
|
||||
|
||||
@@ -69,11 +67,7 @@ public class JSR303Tests 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
|
||||
@@ -82,10 +76,7 @@ public class JSR303Tests 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());
|
||||
}
|
||||
|
||||
@@ -95,10 +86,7 @@ public class JSR303Tests 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());
|
||||
}
|
||||
|
||||
@@ -108,15 +96,12 @@ public class JSR303Tests 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());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = {AdultService.class})
|
||||
@ComponentScan(basePackageClasses = { AdultService.class })
|
||||
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.jsr303.repo")
|
||||
@EnableTransactionManagement
|
||||
static class JSR303Context {
|
||||
@@ -128,7 +113,8 @@ public class JSR303Tests extends MultiDriverTestClass {
|
||||
|
||||
@Bean
|
||||
public SessionFactory sessionFactory() {
|
||||
return new SessionFactory(getBaseConfiguration().build(),"org.springframework.data.neo4j.examples.jsr303.domain");
|
||||
return new SessionFactory(getBaseConfiguration().build(),
|
||||
"org.springframework.data.neo4j.examples.jsr303.domain");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,14 @@ package org.springframework.data.neo4j.examples.movies;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.neo4j.ogm.testutil.GraphTestUtils.*;
|
||||
|
||||
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.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -33,14 +40,26 @@ import org.neo4j.ogm.session.SessionFactory;
|
||||
import org.neo4j.ogm.testutil.MultiDriverTestClass;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
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.Rating;
|
||||
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.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
|
||||
@@ -60,32 +79,22 @@ import org.springframework.transaction.support.TransactionTemplate;
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
@ContextConfiguration(classes = {MoviesIntegrationTests.MoviesContext.class})
|
||||
@ContextConfiguration(classes = { MoviesIntegrationTests.MoviesContext.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MoviesIntegrationTests.class);
|
||||
|
||||
@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;
|
||||
|
||||
@@ -111,7 +120,6 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person)");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldSaveReleasedMovie() {
|
||||
|
||||
@@ -124,8 +132,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
abstractAnnotatedEntityRepository.save(releasedMovie);
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"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
|
||||
@@ -145,14 +153,14 @@ public class MoviesIntegrationTests 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(getGraphDatabaseService(), "CREATE (m:Movie {name:'Pulp Fiction', tags:['cool','classic'], " +
|
||||
"image:'AQID'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE (m:Movie {name:'Pulp Fiction', tags:['cool','classic'], " + "image:'AQID'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -170,12 +178,10 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (:User:Person {name:'Michal'})," +
|
||||
"(:User:Person {name:'Vince'})," +
|
||||
"(:User:Person {name:'Adam'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE (:User:Person {name:'Michal'})," + "(:User:Person {name:'Vince'})," + "(:User:Person {name:'Adam'})");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldSaveUsers2() {
|
||||
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
|
||||
@@ -191,9 +197,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (:User:Person {name:'Michal'})," +
|
||||
"(:User:Person {name:'Vince'})," +
|
||||
"(:User:Person {name:'Adam'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE (:User:Person {name:'Michal'})," + "(:User:Person {name:'Vince'})," + "(:User:Person {name:'Adam'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -210,16 +215,15 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
assertSameGraph(getGraphDatabaseService(), "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(getGraphDatabaseService(), "CREATE (u:User {name:'Adam'})");
|
||||
@@ -261,7 +265,6 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
User user = new User();
|
||||
userRepository.save(user);
|
||||
|
||||
|
||||
Optional<User> loaded = userRepository.findById(user.getId());
|
||||
|
||||
assertTrue(loaded.isPresent());
|
||||
@@ -298,7 +301,6 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldHandleMultipleConcurrentRequests() throws InterruptedException, Neo4jFailedToStartException {
|
||||
|
||||
@@ -324,7 +326,8 @@ public class MoviesIntegrationTests 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
|
||||
@@ -334,7 +337,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
|
||||
userRepository.save(user);
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -346,14 +350,10 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
|
||||
userRepository.save(user);
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "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(getGraphDatabaseService(),
|
||||
"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
|
||||
@@ -363,7 +363,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
|
||||
userRepository.save(user, 1);
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -384,15 +385,11 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(v:User:Person {name:'Vince'})," +
|
||||
"(g:Genre {name:'Drama'})," +
|
||||
"(m)-[:INTERESTED]->(g)," +
|
||||
"(v)-[:INTERESTED]->(g)");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"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");
|
||||
@@ -421,13 +418,10 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(g:Genre {name:'New Drama'})," +
|
||||
"(m)-[:INTERESTED]->(g)");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'New Drama'})," + "(m)-[:INTERESTED]->(g)");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldRemoveGenreFromUser() {
|
||||
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
|
||||
@@ -445,9 +439,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(g:Genre {name:'Drama'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'Drama'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -465,12 +458,10 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(g:Genre {name:'Drama'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'Drama'})");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldAddNewVisitorToCinema() {
|
||||
Cinema cinema = new Cinema("Odeon");
|
||||
@@ -478,10 +469,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
|
||||
cinemaRepository.save(cinema);
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(c:Theatre {name:'Odeon', capacity:0})," +
|
||||
"(m)-[:VISITED]->(c)");
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE " + "(m:User:Person {name:'Michal'}),"
|
||||
+ "(c:Theatre {name:'Odeon', capacity:0})," + "(m)-[:VISITED]->(c)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -499,10 +488,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
});
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE " +
|
||||
"(m:User:Person {name:'Michal'})," +
|
||||
"(c:Theatre {name:'Odeon', capacity:0})," +
|
||||
"(m)-[:VISITED]->(c)");
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE " + "(m:User:Person {name:'Michal'}),"
|
||||
+ "(c:Theatre {name:'Odeon', capacity:0})," + "(m)-[:VISITED]->(c)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -517,9 +504,11 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
});
|
||||
|
||||
try {
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (m:User {name:'Michal'})-[:FRIEND_OF]->(a:User:Person {name:'Adam'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE (m:User {name:'Michal'})-[:FRIEND_OF]->(a:User:Person {name:'Adam'})");
|
||||
} catch (AssertionError error) {
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (m:User:Person {name:'Michal'})<-[:FRIEND_OF]-(a:User:Person {name:'Adam'})");
|
||||
assertSameGraph(getGraphDatabaseService(),
|
||||
"CREATE (m:User:Person {name:'Michal'})<-[:FRIEND_OF]-(a:User:Person {name:'Adam'})");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,8 +553,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
|
||||
User michal = ((Iterable<User>) findByProperty(User.class, "name", "Michal")).iterator().next();
|
||||
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Michal'})-[:RATED {stars:5, " +
|
||||
"comment:'Best movie ever', ratingTimestamp:0}]->(m:Movie {name:'Pulp Fiction'})");
|
||||
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Michal'})-[:RATED {stars:5, "
|
||||
+ "comment:'Best movie ever', ratingTimestamp:0}]->(m:Movie {name:'Pulp Fiction'})");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -575,15 +564,16 @@ public class MoviesIntegrationTests 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());
|
||||
}
|
||||
});
|
||||
@@ -668,7 +658,7 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
|
||||
protected Iterable<?> findByProperty(Class clazz, String propertyName, Object propertyValue) {
|
||||
return session.loadAll(clazz, new Filter(propertyName, ComparisonOperator.EQUALS, propertyValue));
|
||||
return session.loadAll(clazz, new Filter(propertyName, ComparisonOperator.EQUALS, propertyValue));
|
||||
}
|
||||
|
||||
//
|
||||
@@ -680,7 +670,7 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
}
|
||||
|
||||
@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
|
||||
static class MoviesContext {
|
||||
@@ -692,7 +682,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
|
||||
|
||||
@Bean
|
||||
public SessionFactory sessionFactory() {
|
||||
return new SessionFactory(getBaseConfiguration().build(), "org.springframework.data.neo4j.examples.movies.domain");
|
||||
return new SessionFactory(getBaseConfiguration().build(),
|
||||
"org.springframework.data.neo4j.examples.movies.domain");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -92,8 +88,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;
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ package org.springframework.data.neo4j.examples.movies.domain;
|
||||
public interface CinemaAndBlockbuster {
|
||||
|
||||
String getName();
|
||||
|
||||
String getLocation();
|
||||
|
||||
TempMovie getBlockbusterOfTheWeek();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
public interface CinemaAndBlockbusterName {
|
||||
|
||||
Long getId();
|
||||
|
||||
String getName();
|
||||
|
||||
@Value("#{target.blockbusterOfTheWeek.name}")
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user