基於數據傳輸效率以及接口自定義等特殊性需求,咱們暫時放棄使用Neo4j服務器版本,而是在Neo4j嵌入式版本的基礎上進行一些封裝性的開發。封裝的重點,是解決Neo4j嵌入式版本EmbeddedGraphDatabase中不能同時建立多個實例指向同一個數據庫的問題。若是開發人員使用Neo4j嵌入式版本做爲數據庫,要想實現多個程序共享一個數據庫,這將是一個不可迴避的問題。本手冊給出的解決方案是「構建一箇中間服務層,提供各類接口方法,指向同一個數據庫實例;其餘客戶端程序經過中間服務層與Neo4j嵌入式數據庫進行通訊」。由於咱們已經從Neo4j官方聲明中得知:Neo4j嵌入式實例能夠在多個線程中共享。java
系統框架以下圖所示:node
Neo4j Java 工具包是對Neo4j嵌入式版本Java API的二次封裝,根據業務類型劃分爲Node(Relationship)、Index、Path和Cypher等四種工具集。mysql
之因此稱其爲Server端,是由於其中包含了對RMI Server的管理。此管理工具的主要功能包括圖數據庫信息管理(包括新建、刪除、統計圖數據庫等)、圖數據庫數據管理(包括Node數據管理、Relationship數據管理等)、數據導入導出(包括Neo4j與oracle、mysql和excel等之間的數據轉換)、RMI Server監控管理等。sql
管理工具Server端只能部署在Neo4j數據庫服務器上,而且只能部署一套程序,不然將違背Neo4j圖數據庫單例的原則。數據庫
RMI Server(服務),是在Neo4j Java 工具包的基礎上,設計的一套接口服務,分爲Server端和Client端。Server端用於接口方法的實現和監控管理,Client端用於接口方法的定義和分發(供其餘外部系統使用)。整體設計思路,是將Neo4j中的關鍵對象(Node、Relationship、Path、Direction等)進行可序列化的封裝,經過遠程調用服務返回給客戶端使用。apache
管理工具Client端,是基於RMI Client設計的Neo4j數據管理工具,主要功能包括圖數據庫信息查看功能、圖數據庫數據管理功能、數據導入導出功能等。管理工具Client端能夠部署多套。服務器
以上全部功能(工具包、RMI Service以及管理工具)都包含在兩個Java項目中,項目結構以下圖所示:架構
hnepri-neo4j-common爲工具包項目,包括Neo4j Java 工具包、RMI Server端和管理工具Server端;hnepri-neo4j-client爲客戶端項目,包括RMI Client端和管理工具Client端。oracle
下面主要介紹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 * 一、可根據關係類型名稱字符串動態生成關係類型枚舉。<br> 26 * 二、可管理動態生成的關係類型枚舉列表。 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開發