/*
* Hibernate OGM, Domain model persistence for NoSQL datastores
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.ogm.datastore.neo4j.dialect.impl;
import static org.hibernate.ogm.datastore.neo4j.dialect.impl.NodeLabel.EMBEDDED;
import static org.hibernate.ogm.datastore.neo4j.dialect.impl.NodeLabel.ENTITY;
import java.util.Map;
import org.hibernate.ogm.model.key.spi.EntityKeyMetadata;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.cypher.javacompat.ExecutionResult;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.ResourceIterator;
/**
* Container for the queries related to one entity type in Neo4j. Unfortunately, we cannot use the same queries for all
* entities, as Neo4j does not allow to parameterize on node labels which would be required, as the entity name is
* stored as a label.
*
* @author Davide D'Alto
*/
public class Neo4jEntityQueries extends QueriesBase {
private final String createEmbeddedNodeQuery;
private final String findEntityQuery;
private final String findEntitiesQuery;
private final String findOrCreateEntityQuery;
private final String removeEntityQuery;
public Neo4jEntityQueries(EntityKeyMetadata entityKeyMetadata) {
this.createEmbeddedNodeQuery = initCreateEmbeddedNodeQuery( entityKeyMetadata );
this.findEntityQuery = initFindEntityQuery( entityKeyMetadata );
this.findEntitiesQuery = initFindEntitiesQuery( entityKeyMetadata );
this.findOrCreateEntityQuery = initFindOrCreateEntityQuery( entityKeyMetadata );
this.removeEntityQuery = initRemoveEntityQuery( entityKeyMetadata );
}
/*
* Example:
*
* CREATE (n:EMBEDDED:table {id: {0}})
* RETURN n
*/
private static String initCreateEmbeddedNodeQuery(EntityKeyMetadata entityKeyMetadata) {
StringBuilder queryBuilder = new StringBuilder( "CREATE " );
queryBuilder.append( "(n:" );
queryBuilder.append( EMBEDDED );
queryBuilder.append( ":" );
appendLabel( entityKeyMetadata, queryBuilder );
appendProperties( entityKeyMetadata, queryBuilder );
queryBuilder.append( ")" );
queryBuilder.append( " RETURN n" );
return queryBuilder.toString();
}
/*
* Example:
*
* MATCH (n:ENTITY:table {id: {0}})
* RETURN n
*/
private static String initFindEntityQuery(EntityKeyMetadata entityKeyMetadata) {
StringBuilder queryBuilder = new StringBuilder( "MATCH " );
queryBuilder.append( "(n:" );
queryBuilder.append( ENTITY );
queryBuilder.append( ":" );
appendLabel( entityKeyMetadata, queryBuilder );
appendProperties( entityKeyMetadata, queryBuilder );
queryBuilder.append( ")" );
queryBuilder.append( " RETURN n" );
return queryBuilder.toString();
}
/*
* Example:
*
* MATCH (n:ENTITY:table )
* RETURN n
*/
private static String initFindEntitiesQuery(EntityKeyMetadata entityKeyMetadata) {
StringBuilder queryBuilder = new StringBuilder( "MATCH " );
queryBuilder.append( "(n:" );
queryBuilder.append( ENTITY );
queryBuilder.append( ":" );
appendLabel( entityKeyMetadata, queryBuilder );
queryBuilder.append( ") RETURN n" );
return queryBuilder.toString();
}
/*
* Example:
*
* MERGE (n:ENTITY:table {id: {0}})
* RETURN n
*/
private static String initFindOrCreateEntityQuery(EntityKeyMetadata entityKeyMetadata) {
StringBuilder queryBuilder = new StringBuilder( "MERGE " );
queryBuilder.append( "(n:" );
queryBuilder.append( ENTITY );
queryBuilder.append( ":" );
appendLabel( entityKeyMetadata, queryBuilder );
appendProperties( entityKeyMetadata, queryBuilder );
queryBuilder.append( ")" );
queryBuilder.append( " RETURN n" );
return queryBuilder.toString();
}
/*
* Example:
*
* MATCH (n:ENTITY:table {id: {0}})
* OPTIONAL MATCH (n) - [r] - ()
* DELETE n, r
*/
private static String initRemoveEntityQuery(EntityKeyMetadata entityKeyMetadata) {
StringBuilder queryBuilder = new StringBuilder( "MATCH " );
queryBuilder.append( "(n:" );
queryBuilder.append( ENTITY );
queryBuilder.append( ":" );
appendLabel( entityKeyMetadata, queryBuilder );
appendProperties( entityKeyMetadata, queryBuilder );
queryBuilder.append( ")" );
queryBuilder.append( " OPTIONAL MATCH (n) - [r] - ()" );
queryBuilder.append( " DELETE n, r" );
return queryBuilder.toString();
}
/**
* Create a single node representing an embedded element.
*
* @param executionEngine the {@link ExecutionEngine} used to run the query
* @param columnValues the values in {@link org.hibernate.ogm.model.key.spi.EntityKey#getColumnValues()}
* @return the corresponding node;
*/
public Node createEmbedded(ExecutionEngine executionEngine, Object[] columnValues) {
Map<String, Object> params = params( columnValues );
ExecutionResult result = executionEngine.execute( createEmbeddedNodeQuery, params );
return singleResult( result );
}
/**
* Find the node corresponding to an entity.
*
* @param executionEngine the {@link ExecutionEngine} used to run the query
* @param columnValues the values in {@link org.hibernate.ogm.model.key.spi.EntityKey#getColumnValues()}
* @return the corresponding node
*/
public Node findEntity(ExecutionEngine executionEngine, Object[] columnValues) {
Map<String, Object> params = params( columnValues );
ExecutionResult result = executionEngine.execute( findEntityQuery, params );
return singleResult( result );
}
/**
* Find the node corresponding to an entity or create it if it does not exist.
*
* @param executionEngine the {@link ExecutionEngine} used to run the query
* @param columnValues the values in {@link org.hibernate.ogm.model.key.spi.EntityKey#getColumnValues()}
* @return the corresponding node
*/
public Node findOrCreateEntity(ExecutionEngine executionEngine, Object[] columnValues) {
Map<String, Object> params = params( columnValues );
ExecutionResult result = executionEngine.execute( findOrCreateEntityQuery, params );
return singleResult( result );
}
/**
* Find all the node representing the entity.
*
* @param executionEngine the {@link ExecutionEngine} used to run the query
* @return
*/
public ResourceIterator<Node> findEntities(ExecutionEngine executionEngine) {
ExecutionResult result = executionEngine.execute( findEntitiesQuery );
return result.columnAs( "n" );
}
/**
* Remove the nodes representing the entity.
*
* @param executionEngine the {@link ExecutionEngine} used to run the query
*/
public void removeEntity(ExecutionEngine executionEngine, Object[] columnValues) {
Map<String, Object> params = params( columnValues );
executionEngine.execute( removeEntityQuery, params );
}
}