标签:
基于数据传输效率以及接口自定义等特殊性需求,我们暂时放弃使用Neo4j服务器版本,而是在Neo4j嵌入式版本的基础上进行一些封装性的开发。封装的重点,是解决Neo4j嵌入式版本EmbeddedGraphDatabase中不能同时创建多个实例指向同一个数据库的问题。如果开发人员使用Neo4j嵌入式版本作为数据库,要想实现多个程序共享一个数据库,这将是一个不可回避的问题。本手册给出的解决方案是“构建一个中间服务层,提供各种接口方法,指向同一个数据库实例;其他客户端程序通过中间服务层与Neo4j嵌入式数据库进行通信”。因为我们已经从Neo4j官方声明中得知:Neo4j嵌入式实例可以在多个线程中共享。
系统框架如下图所示:
Neo4j Java 工具包是对Neo4j嵌入式版本Java API的二次封装,根据业务类型划分为Node(Relationship)、Index、Path和Cypher等四种工具集。
之所以称其为Server端,是因为其中包含了对RMI Server的管理。此管理工具的主要功能包括图数据库信息管理(包括新建、删除、统计图数据库等)、图数据库数据管理(包括Node数据管理、Relationship数据管理等)、数据导入导出(包括Neo4j与oracle、mysql和excel等之间的数据转换)、RMI Server监控管理等。
管理工具Server端只能部署在Neo4j数据库服务器上,并且只能部署一套程序,否则将违背Neo4j图数据库单例的原则。
RMI Server(服务),是在Neo4j Java 工具包的基础上,设计的一套接口服务,分为Server端和Client端。Server端用于接口方法的实现和监控管理,Client端用于接口方法的定义和分发(供其他外部系统使用)。总体设计思路,是将Neo4j中的关键对象(Node、Relationship、Path、Direction等)进行可序列化的封装,通过远程调用服务返回给客户端使用。
管理工具Client端,是基于RMI Client设计的Neo4j数据管理工具,主要功能包括图数据库信息查看功能、图数据库数据管理功能、数据导入导出功能等。管理工具Client端可以部署多套。
以上所有功能(工具包、RMI Service以及管理工具)都包含在两个Java项目中,项目结构如下图所示:
hnepri-neo4j-common为工具包项目,包括Neo4j Java 工具包、RMI Server端和管理工具Server端;hnepri-neo4j-client为客户端项目,包括RMI Client端和管理工具Client端。
下面主要介绍Neo4j Java 工具包的几个封装关键点,其中,下图为各个工具类之间的关联效果图。
Node操作工具类的主要功能包括Node节点和Relationship关系的创建、编辑、删除、查询,以及Label和Property的管理等。对于其中的部分接口方法,根据实际情况和需要则进行了事务处理。相关接口方法截图如下所示:
Index操作工具类的主要功能包括Node和Relationship相关索引信息的创建、编辑、删除、查询,以及基于索引查询Node节点和Relationship关系等。对于其中的部分接口方法,根据实际情况和需要则进行了事务处理。相关接口方法截图如下所示:
Path操作工具类的主要功能包括针对Path的检索操作,包括路径深度遍历、两点之间路径寻址等接口方法。对于其中的部分接口方法,根据实际情况和需要则进行了事务处理。相关接口方法截图如下所示:
Cypher操作工具类是对Cypher查询语言的封装,主要包括针对Node、Relationship和Path的自定义查询操作。另外,也包括了多种方式的分页查询。对于其中的部分接口方法,根据实际情况和需要则进行了事务处理。
其中,最基本的接口方法是executeQuery方法,执行Cypher查询语句,将查询结果以Properties的形式存在在List中,然后再由其他接口方法显式地转换为Node、Relationship、Path或者其他基本类型使用。
1 /** 2 * 执行Cypher查询语句,将检索结果封装进Properties列表中。 3 * @param query cypher查询语句 4 * @param params cypher查询语句参数集合 5 * @return 6 */ 7 public List<Properties> executeQuery(String query, Map<String,Object> params) { 8 GraphTimerModel timer = GraphTimerModel.create(); 9 List<Properties> propertiesList = new ArrayList<Properties>(); 10 if(StringUtils.isBlank(query)) { 11 return propertiesList; 12 } 13 ExecutionResult result = null; 14 if(params == null || params.size() == 0) { 15 result = this.getExecutionEngine().execute(query); 16 } else { 17 result = this.getExecutionEngine().execute(query, params); 18 } 19 LogInfoUtil.printLog(query); 20 21 for (Map<String, Object> row : result ) { 22 Properties properties = new Properties(); 23 for ( Entry<String, Object> column : row.entrySet()){ 24 properties.put(column.getKey(), column.getValue()); 25 } 26 propertiesList.add(properties); 27 } 28 timer.initEndTime(); 29 timer.printTimeInfo(); 30 return propertiesList; 31 } 32 举例如下所示: 33 String query = "START n=node(*) WHERE n.name=’tom’ RETURN n AS NODE_ENTRY"; 34 List<Properties> list = this.executeQuery(query); 35 for(Properties properties : list) { 36 nodeList.add((Node)properties.get("NODE_ENTRY")); 37 }
相关接口方法截图如下所示:
动态生成RelationshipType是构建RMI服务必须首先要解决的一个关键点,因为RMI要求Server端与Client端之间的传输对象必须是可序列化的对象,而Neo4j API中的接口类和枚举是无法真正序列化的,这也是我们在RMI Service中对相关实体进行封装的根本原因。
所谓动态生成RelationshipType,就是可根据字符串类型的关系类型,生成符合Neo4j Java API要求的枚举类型RelationshipType。关键代码如下表所示:
1 package com.hnepri.neo4j.common.util; 2 3 import java.lang.reflect.AccessibleObject; 4 import java.lang.reflect.Array; 5 import java.lang.reflect.Field; 6 import java.lang.reflect.Modifier; 7 import java.util.ArrayList; 8 import java.util.Arrays; 9 import java.util.HashMap; 10 import java.util.Iterator; 11 import java.util.List; 12 import java.util.Map; 13 14 import org.apache.commons.lang3.StringUtils; 15 import org.neo4j.graphdb.GraphDatabaseService; 16 import org.neo4j.graphdb.RelationshipType; 17 import org.neo4j.graphdb.Transaction; 18 19 import sun.reflect.ConstructorAccessor; 20 import sun.reflect.FieldAccessor; 21 import sun.reflect.ReflectionFactory; 22 23 /** 24 * Description: 图数据库关系类型工具类。<br> 25 * 1、可根据关系类型名称字符串动态生成关系类型枚举。<br> 26 * 2、可管理动态生成的关系类型枚举列表。 27 * Copyright: Copyright (c) 2015<br> 28 * Company: 河南电力科学研究院智能电网所<br> 29 * @author shangbingbing 2015-11-01编写 30 * @version 1.0 31 */ 32 public class GraphRelTypeUtil { 33 34 /** 35 * 构造函数。<br> 36 * 初始化对应的图数据库服务对象实例。 37 * @param graphDBService 38 */ 39 public GraphRelTypeUtil(GraphDatabaseService graphDBService) { 40 this.graphDBService = graphDBService; 41 } 42 43 private GraphDatabaseService graphDBService = null; 44 /** 45 * 获取对应的图数据库服务对象实例。 46 * @return 47 */ 48 public GraphDatabaseService getGraphDBService() { 49 return this.graphDBService; 50 } 51 52 /** 53 * 构建事务。 54 * @return 55 */ 56 public Transaction createTransaction() { 57 return this.getGraphDBService().beginTx(); 58 } 59 60 private GraphIndexUtil indexManager = null; 61 /** 62 * 获取图数据库索引信息管理器。 63 * @return 64 */ 65 public GraphIndexUtil getIndexManager() { 66 if(this.indexManager == null) { 67 this.indexManager = new GraphIndexUtil(this.getGraphDBService()); 68 } 69 return this.indexManager; 70 } 71 72 private Map<String,RelationshipType> relationshipTypeList = null; 73 /** 74 * 获取已动态生成的关系枚举类型列表。 75 * @return 76 */ 77 @SuppressWarnings("deprecation") 78 public Map<String, RelationshipType> getRelationshipTypeList() { 79 if(this.relationshipTypeList == null) { 80 this.relationshipTypeList = new HashMap<String, RelationshipType>(); 81 82 Iterator<RelationshipType> iterator = this.getGraphDBService().getRelationshipTypes().iterator(); 83 while(iterator.hasNext()) { 84 RelationshipType relType = iterator.next(); 85 String relTypeName = relType.name(); 86 this.relationshipTypeList.put(relTypeName, relType); 87 } 88 } 89 return this.relationshipTypeList; 90 } 91 92 /** 93 * 根据关系类型名称动态生成图数据库关系枚举类型。 94 * @param relTypeName 95 * @return 96 */ 97 public RelationshipType create(String relTypeName) { 98 if(StringUtils.isBlank(relTypeName)) { 99 return null; 100 } 101 if(this.getRelationshipTypeList().containsKey(relTypeName) == false) { 102 addEnum(relTypeName); 103 RelationshipType relType = RelationshipTypeEnum.valueOf(relTypeName); 104 this.getRelationshipTypeList().put(relTypeName, relType); 105 return relType; 106 } else { 107 return this.getRelationshipTypeList().get(relTypeName); 108 } 109 } 110 111 /** 112 * 根据关系类型名称,获取对应的关系枚举类型。 113 * @param relTypeName 114 * @return 115 */ 116 public RelationshipType get(String relTypeName) { 117 if(StringUtils.isBlank(relTypeName)) { 118 return null; 119 } 120 return this.create(relTypeName); 121 } 122 123 /** 124 * 根据关系类型名称,删除对应的关系枚举类型。 125 * @param relTypeName 126 * @return 127 */ 128 public void remove(String relTypeName) { 129 if(this.getRelationshipTypeList().containsKey(relTypeName)) { 130 this.getRelationshipTypeList().remove(relTypeName); 131 } 132 } 133 134 /** 135 * 根据关系类型名称列表,初始化关系类型枚举列表。 136 * @param relTypeNameList 137 */ 138 public void init(List<String> relTypeNameList) { 139 if(relTypeNameList == null || relTypeNameList.size() == 0) { 140 return; 141 } 142 for(String relTypeName : relTypeNameList) { 143 create(relTypeName); 144 } 145 } 146 147 private static ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory(); 148 149 private static void setFailsafeFieldValue(Field field, Object target, Object value) throws NoSuchFieldException,IllegalAccessException { 150 field.setAccessible(true); 151 Field modifiersField = Field.class.getDeclaredField("modifiers"); 152 modifiersField.setAccessible(true); 153 int modifiers = modifiersField.getInt(field); 154 155 modifiers &= ~Modifier.FINAL; 156 modifiersField.setInt(field, modifiers); 157 158 FieldAccessor fa = reflectionFactory.newFieldAccessor(field, false); 159 fa.set(target, value); 160 } 161 162 private static void blankField(Class<?> enumClass, String fieldName) throws NoSuchFieldException, IllegalAccessException { 163 for (Field field : Class.class.getDeclaredFields()) { 164 if (field.getName().contains(fieldName)) { 165 AccessibleObject.setAccessible(new Field[] { field }, true); 166 setFailsafeFieldValue(field, enumClass, null); 167 break; 168 } 169 } 170 } 171 172 private static void cleanEnumCache(Class<?> enumClass) throws NoSuchFieldException, IllegalAccessException { 173 blankField(enumClass, "enumConstantDirectory"); 174 blankField(enumClass, "enumConstants"); 175 } 176 177 private static ConstructorAccessor getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws NoSuchMethodException { 178 Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2]; 179 parameterTypes[0] = String.class; 180 parameterTypes[1] = int.class; 181 System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length); 182 return reflectionFactory.newConstructorAccessor(enumClass.getDeclaredConstructor(parameterTypes)); 183 } 184 185 private static Object makeEnum(Class<?> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception { 186 Object[] parms = new Object[additionalValues.length + 2]; 187 parms[0] = value; 188 parms[1] = Integer.valueOf(ordinal); 189 System.arraycopy(additionalValues, 0, parms, 2, additionalValues.length); 190 return enumClass.cast(getConstructorAccessor(enumClass, additionalTypes).newInstance(parms)); 191 } 192 193 @SuppressWarnings("unchecked") 194 private static <T extends Enum<?>> void addEnum(String enumName) { 195 if (!Enum.class.isAssignableFrom(RelationshipTypeEnum.class)) { 196 throw new RuntimeException("class " + RelationshipTypeEnum.class + " is not an instance of Enum"); 197 } 198 199 Field valuesField = null; 200 Field[] fields = RelationshipTypeEnum.class.getDeclaredFields(); 201 for (Field field : fields) { 202 if (field.getName().contains("$VALUES")) { 203 valuesField = field; 204 break; 205 } 206 } 207 AccessibleObject.setAccessible(new Field[] { valuesField }, true); 208 209 try { 210 211 T[] previousValues = (T[]) valuesField.get(RelationshipTypeEnum.class); 212 List<T> values = new ArrayList<T>(Arrays.asList(previousValues)); 213 214 T newValue = (T) makeEnum(RelationshipTypeEnum.class, enumName, values.size(), new Class<?>[] {}, new Object[] {}); 215 values.add(newValue); 216 setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(RelationshipTypeEnum.class, 0))); 217 cleanEnumCache(RelationshipTypeEnum.class); 218 } catch (Exception e) { 219 e.printStackTrace(); 220 throw new RuntimeException(e.getMessage(), e); 221 } 222 } 223 } 224 225 /** 226 * Description: 图数据库关系类型枚举。 227 * Copyright: Copyright (c) 2015<br> 228 * Company: 河南电力科学研究院智能电网所<br> 229 * @author shangbingbing 2015-11-01编写 230 * @version 1.0 231 */ 232 enum RelationshipTypeEnum implements RelationshipType { 233 NONE 234 }
图数据库操作模板工具类,主要负责对以上工具集的组织和调用管理,以保证开发人员在调用习惯上遵循Neo4j嵌入式图数据库单例服务的原则。关键代码如下表所示:
1 package com.hnepri.neo4j.common.util; 2 3 import java.io.File; 4 import java.util.HashMap; 5 import java.util.Map; 6 7 import org.apache.commons.lang3.StringUtils; 8 import org.neo4j.graphdb.GraphDatabaseService; 9 import org.neo4j.graphdb.Transaction; 10 import org.neo4j.graphdb.factory.GraphDatabaseFactory; 11 import org.neo4j.io.fs.FileUtils; 12 13 import com.hnepri.neo4j.client.form.graph.bean.GraphConfigOption; 14 import com.hnepri.neo4j.form.graph.util.GraphManageUtil; 15 16 /** 17 * Description: Neo4j图数据库操作模板类。<br> 18 * Copyright: Copyright (c) 2015<br> 19 * Company: 河南电力科学研究院智能电网所<br> 20 * @author shangbingbing 2015-11-01 编写 21 * @version 1.0 22 */ 23 public class GraphTemplate { 24 25 private String graphDBPath = ""; 26 /** 27 * 获取图数据库路径。 28 * @return 29 */ 30 public String getGraphDBPath() { 31 return graphDBPath; 32 } 33 private GraphDatabaseService graphDBService = null; 34 /** 35 * 获取图数据库服务实例对象。 36 * @return 37 */ 38 public GraphDatabaseService getGraphDBService() { 39 if(StringUtils.isBlank(this.getGraphDBPath())) { 40 try { 41 throw new Exception("警告:没有配置图数据库路径信息!"); 42 } catch (Exception e) { 43 e.printStackTrace(); 44 } 45 } 46 if(this.graphDBService == null) { 47 this.graphDBService = new GraphDatabaseFactory().newEmbeddedDatabase(this.getGraphDBPath()); 48 registerShutdownHook(); 49 } 50 return this.graphDBService; 51 } 52 53 /** 54 * 清除图数据库数据文件信息。 55 */ 56 public void clearGraphDB() { 57 try { 58 FileUtils.deleteRecursively(new File(this.getGraphDBPath())); 59 if(graphTemplateList.containsKey(this.getGraphDBPath())) { 60 graphTemplateList.remove(this.getGraphDBPath()); 61 } 62 } catch (Exception ex) { 63 ex.printStackTrace(); 64 } 65 } 66 67 /** 68 * 注册图数据库关闭钩子。 69 */ 70 public void registerShutdownHook() { 71 Runtime.getRuntime().addShutdownHook(new Thread(){ 72 @Override 73 public void run(){ 74 getGraphDBService().shutdown(); 75 } 76 }); 77 } 78 79 /** 80 * 构造函数。初始化图数据库路径。 81 * @param graphDBPath 82 */ 83 private GraphTemplate(String graphDBPath) { 84 this.graphDBPath = graphDBPath; 85 } 86 87 private static Map<String, GraphTemplate> graphTemplateList = new HashMap<String, GraphTemplate>(); 88 /** 89 * 根据图数据库路径信息,获取对应的GraphTemplate对象实例。<br> 90 * 目的是采用GraphTemplate的单例模式。 91 * @param graphPath 92 * @return 93 */ 94 public static GraphTemplate getInstance(String graphPath) { 95 if(graphTemplateList.containsKey(graphPath) == false) { 96 GraphTemplate template = new GraphTemplate(graphPath); 97 graphTemplateList.put(graphPath, template); 98 } 99 return graphTemplateList.get(graphPath); 100 } 101 102 /** 103 * 根据图数据库名称标示信息,获取对应的GraphTemplate对象实例。<br> 104 * 目的是采用GraphTemplate的单例模式。 105 * @param graphName 106 * @return 107 */ 108 public static GraphTemplate getInstanceByName(String graphName) { 109 if(GraphManageUtil.getGraphConfigOptionList().containsKey(graphName) == false) { 110 return null; 111 } 112 GraphConfigOption option = GraphManageUtil.getGraphConfigOptionList().get(graphName); 113 return getInstance(option.getPath()); 114 } 115 116 /** 117 * 构建事务。 118 * @return 119 */ 120 public Transaction createTransaction() { 121 return this.getGraphDBService().beginTx(); 122 } 123 124 private GraphIndexUtil indexUtil = null; 125 /** 126 * 获取图数据库索引信息管理功能库。 127 * @return 128 */ 129 public GraphIndexUtil getIndexUtil() { 130 if(this.indexUtil == null) { 131 this.indexUtil = new GraphIndexUtil(this.getGraphDBService()); 132 } 133 return this.indexUtil; 134 } 135 136 private GraphNodeUtil nodeUtil = null; 137 /** 138 * 获取图数据库节点信息管理功能库。 139 * @return 140 */ 141 public GraphNodeUtil getNodeUtil() { 142 if(this.nodeUtil == null) { 143 this.nodeUtil = new GraphNodeUtil(this.getGraphDBService()); 144 } 145 return this.nodeUtil; 146 } 147 148 private GraphCypherUtil cypherUtil = null; 149 /** 150 * 获取图数据库Cypher查询语言功能库。 151 * @return 152 */ 153 public GraphCypherUtil getCypherUtil() { 154 if(this.cypherUtil == null) { 155 this.cypherUtil = new GraphCypherUtil(this.getGraphDBService()); 156 } 157 return this.cypherUtil; 158 } 159 160 private GraphPathUtil pathUtil = null; 161 /** 162 * 获取图数据库Path信息功能库。 163 * @return 164 */ 165 public GraphPathUtil getPathUtil() { 166 if(this.pathUtil == null) { 167 this.pathUtil = new GraphPathUtil(this.getGraphDBService()); 168 } 169 return this.pathUtil; 170 } 171 172 private GraphRelTypeUtil relTypeUtil = null; 173 /** 174 * 获取图数据库关系类型信息功能库。 175 * @return 176 */ 177 public GraphRelTypeUtil getRelTypeUtil() { 178 if(this.relTypeUtil == null) { 179 this.relTypeUtil = new GraphRelTypeUtil(this.getGraphDBService()); 180 } 181 return this.relTypeUtil; 182 } 183 }
数据分页模型主要是基于Cypher查询语言中的SKIP和LIMIT而设计的针对Node和Relationship的分页处理模型。关键代码如下表所示:
1 package com.hnepri.neo4j.common.model; 2 3 import java.io.Serializable; 4 import java.text.DecimalFormat; 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import org.neo4j.graphdb.Node; 9 import org.neo4j.graphdb.Relationship; 10 11 import com.hnepri.common.util.LogInfoUtil; 12 13 /** 14 * Description: 图数据库数据分页模型类。<br> 15 * 利用此类可分页管理Node数据和Relationship数据等。 16 * Copyright: Copyright (c) 2015<br> 17 * Company: 河南电力科学研究院智能电网所<br> 18 * @author shangbingbing 2015-11-01编写 19 * @version 1.0 20 */ 21 public class GraphPageModel implements Serializable { 22 private static final long serialVersionUID = 330410716100946538L; 23 private int pageSize = 10; 24 private int pageIndex = 1; 25 private int prevPageIndex = 1; 26 private int nextPageIndex = 1; 27 private int pageCount = 0; 28 private int pageFirstRowIndex = 1; 29 private boolean hasNextPage = true; 30 private int totalCount = 0; 31 private long startTime = System.currentTimeMillis(); 32 private long endTime = System.currentTimeMillis(); 33 private List<Node> nodeList = new ArrayList<Node>(); 34 private List<Relationship> relationshipList = new ArrayList<Relationship>(); 35 36 /** 37 * 分页对象构造函数 38 * @param pageSize 每页记录数 39 */ 40 public GraphPageModel(int pageSize) { 41 this.pageSize = pageSize; 42 } 43 44 /** 45 * 获取分页记录数量 46 * @return 47 */ 48 public int getPageSize() { 49 return pageSize; 50 } 51 /** 52 * 获取当前页序号 53 * @return 54 */ 55 public int getPageIndex() { 56 return pageIndex; 57 } 58 /** 59 * 设置当前页序号 60 * @param pageIndex 61 */ 62 public void setPageIndex(int pageIndex) { 63 if(pageIndex <= 0) { 64 pageIndex = 1; 65 } 66 this.pageIndex = pageIndex; 67 } 68 /** 69 * 获取分页总数 70 * @return 71 */ 72 public int getPageCount() { 73 if(this.getTotalCount() == 0) { 74 this.pageCount = 0; 75 } else { 76 int shang = this.getTotalCount() / this.getPageSize(); 77 int yu = this.getTotalCount() % this.getPageSize(); 78 if(yu > 0) { 79 shang += 1; 80 } 81 this.pageCount = shang; 82 } 83 return pageCount; 84 } 85 /** 86 * 获取每页的第一行序号 87 * @return 88 */ 89 public int getPageFirstRowIndex() { 90 this.pageFirstRowIndex = (this.pageIndex - 1) * this.getPageSize() + 1; 91 return pageFirstRowIndex; 92 } 93 /** 94 * 获取上一页序号 95 * @return 96 */ 97 public int getPrevPageIndex() { 98 if(this.pageIndex > 1) { 99 this.prevPageIndex = this.pageIndex - 1; 100 } else { 101 this.prevPageIndex = 1; 102 } 103 return prevPageIndex; 104 } 105 /** 106 * 获取下一页序号 107 * @return 108 */ 109 public int getNextPageIndex() { 110 if(this.pageIndex < this.pageCount) { 111 this.nextPageIndex = this.pageIndex + 1; 112 } else { 113 this.nextPageIndex = this.pageCount; 114 } 115 return nextPageIndex; 116 } 117 /** 118 * 跳转到下一页 119 */ 120 public void nextPage() { 121 if(this.totalCount == 0 || this.getPageCount() == 0) { 122 this.pageIndex = 1; 123 } else { 124 if(this.pageIndex < this.pageCount) { 125 this.pageIndex = this.pageIndex + 1; 126 } else { 127 this.pageIndex = this.pageCount; 128 } 129 } 130 } 131 /** 132 * 跳转到上一页 133 */ 134 public void prevPage() { 135 if(this.pageIndex > 1) { 136 this.pageIndex = this.pageIndex - 1; 137 } else { 138 this.pageIndex = 1; 139 } 140 } 141 /** 142 * 获取是否有下一页 143 * @return 144 */ 145 public boolean isHasNextPage() { 146 if(this.pageIndex < this.getPageCount()) { 147 this.hasNextPage = true; 148 } else { 149 this.hasNextPage = false; 150 } 151 return hasNextPage; 152 } 153 /** 154 * 获取总记录数 155 */ 156 public int getTotalCount() { 157 return totalCount; 158 } 159 /** 160 * 获取总记录数 161 * @param totalCount 162 */ 163 public void setTotalCount(int totalCount) { 164 this.totalCount = totalCount; 165 } 166 /** 167 * 初始化起始时间(毫秒) 168 */ 169 public void initStartTime() { 170 this.startTime = System.currentTimeMillis(); 171 } 172 /** 173 * 初始化截止时间(毫秒) 174 */ 175 public void initEndTime() { 176 this.endTime = System.currentTimeMillis(); 177 } 178 /** 179 * 获取毫秒格式的耗时信息 180 * @return 181 */ 182 public String getTimeIntervalByMilli() { 183 return String.valueOf(this.endTime - this.startTime) + "毫秒"; 184 } 185 /** 186 * 获取秒格式的耗时信息 187 * @return 188 */ 189 public String getTimeIntervalBySecond() { 190 double interval = (this.endTime - this.startTime)/1000.0; 191 DecimalFormat df = new DecimalFormat("#.##"); 192 return df.format(interval) + "秒"; 193 } 194 /** 195 * 打印时间信息 196 */ 197 public void printTimeInfo() { 198 LogInfoUtil.printLog("起始时间:" + this.startTime); 199 LogInfoUtil.printLog("截止时间:" + this.endTime); 200 LogInfoUtil.printLog("耗费时间:" + this.getTimeIntervalBySecond()); 201 } 202 /** 203 * 获取Node检索结果列表 204 * @return 205 */ 206 public List<Node> getNodeList() { 207 return nodeList; 208 } 209 /** 210 * 获取Relationship检索结果列表 211 * @return 212 */ 213 public List<Relationship> getRelationshipList() { 214 return relationshipList; 215 } 216 }
【未完待续】
下一篇 Neo4j图数据库应用开发之二:RMI Service开发
Neo4j图数据库应用开发之一:Neo4j Java 工具包
标签:
原文地址:http://www.cnblogs.com/shangbingbing/p/5026146.html