Spring数据Neo4j ogm会话问题与loadAll的id和深度

时间:2016-11-04 08:12:13

标签: java spring neo4j spring-data-neo4j

我有一个类似于此的图表:

(t:Teacher)-[:TEACHES]-(s:Student)-[:ATTENDS]-(s:Subject)-[:REQUIRES]-(b:Book)

@NodeEntity类表示。

我需要为具有给定范围的ID的教师加载所有@NodeEntities,并在一个查询中获取他们所教授的所有学生,以及每个科目所需的科目和书籍。

我试过

int depth=3;
List<Long> ids = newArrayList(3,4,5);
session.loadAll(Teacher.class, ids, depth);

我实际上是从相应的GraphRepository findAll开始的,这是一回事。

不幸的是,我得到了数据库中所有可用教师的列表,因为每个学生都是由所有教师教授的。我也试过运行自定义@Query,虽然看起来你不能指定自定义深度How to control depth on custom Spring Data Neo4j repository methods?,也不能从自定义密码查询中返回多个节点。

你知道为什么我的做法错了吗?这个接缝是对neo4j的一个简单使用,我一直在抓取整个图形。

1 个答案:

答案 0 :(得分:0)

是的,当您使用模型将//#define _USE_NT_VERSION_ class SPYDATA : #ifdef _USE_NT_VERSION_ IO_STATUS_BLOCK #else OVERLAPPED #endif { HANDLE _hFile; LONG _dwRef; union { FILE_NOTIFY_INFORMATION _fni; UCHAR _buf[PAGE_SIZE]; }; void DumpDirectoryChanges() { union { PVOID buf; PBYTE pb; PFILE_NOTIFY_INFORMATION pfni; }; buf = _buf; for (;;) { DbgPrint("%x <%.*S>\n", pfni->Action, pfni->FileNameLength >> 1, pfni->FileName); ULONG NextEntryOffset = pfni->NextEntryOffset; if (!NextEntryOffset) { break; } pb += NextEntryOffset; } } #ifdef _USE_NT_VERSION_ static VOID WINAPI _OvCompRoutine( _In_ NTSTATUS dwErrorCode, _In_ ULONG_PTR dwNumberOfBytesTransfered, _Inout_ PIO_STATUS_BLOCK Iosb ) { static_cast<SPYDATA*>(Iosb)->OvCompRoutine(dwErrorCode, (ULONG)dwNumberOfBytesTransfered); } #else static VOID WINAPI _OvCompRoutine( _In_ DWORD dwErrorCode, // really this is NTSTATUS _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped ) { static_cast<SPYDATA*>(lpOverlapped)->OvCompRoutine(dwErrorCode, dwNumberOfBytesTransfered); } #endif VOID OvCompRoutine(NTSTATUS status, DWORD dwNumberOfBytesTransfered) { DbgPrint("[%x,%x]\n", status, dwNumberOfBytesTransfered); if (0 <= status) { if (status != STATUS_NOTIFY_CLEANUP) { if (dwNumberOfBytesTransfered) DumpDirectoryChanges(); process_list_of_existing_files();// so hard do this here ?!? DoRead(); } else { DbgPrint("\n---- NOTIFY_CLEANUP -----\n"); } } Release(); MyReleaseRundownProtection(); } ~SPYDATA() { Cancel(); } public: void DoRead() { if (MyAcquireRundownProtection()) { AddRef(); #ifdef _USE_NT_VERSION_ NTSTATUS status = ZwNotifyChangeDirectoryFile(_hFile, 0, 0, this, this, &_fni, sizeof(_buf), FILE_NOTIFY_VALID_MASK, TRUE); if (NT_ERROR(status)) { OvCompRoutine(status, 0); } #else if (!ReadDirectoryChangesW(_hFile, _buf, sizeof(_buf), TRUE, FILE_NOTIFY_VALID_MASK, (PDWORD)&InternalHigh, this, 0)) { OvCompRoutine(RtlGetLastNtStatus(), 0); } #endif } } SPYDATA() { _hFile = 0;// ! not INVALID_HANDLE_VALUE because use ntapi for open file _dwRef = 1; #ifndef _USE_NT_VERSION_ RtlZeroMemory(static_cast<OVERLAPPED*>(this), sizeof(OVERLAPPED)); #endif } void AddRef() { InterlockedIncrement(&_dwRef); } void Release() { if (!InterlockedDecrement(&_dwRef)) { delete this; } } BOOL Create(POBJECT_ATTRIBUTES poa) { IO_STATUS_BLOCK iosb; NTSTATUS status = ZwOpenFile(&_hFile, FILE_GENERIC_READ, poa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE); if (0 <= status) { return #ifdef _USE_NT_VERSION_ 0 <= RtlSetIoCompletionCallback(_hFile, _OvCompRoutine, 0); #else BindIoCompletionCallback(_hFile, _OvCompRoutine, 0); #endif } return FALSE; } void Cancel() { if (HANDLE hFile = InterlockedExchangePointer(&_hFile, 0)) { NtClose(hFile); } } }; void DemoF() { if (MyInitializeRundownProtection()) { STATIC_OBJECT_ATTRIBUTES(oa, "<SOME_DIRECTORY>"); if (SPYDATA* p = new SPYDATA) { if (p->Create(&oa)) { p->DoRead(); } //++ GUI thread run MessageBoxW(0, L"wait close program...", L"", MB_OK); //-- GUI thread end p->Cancel(); p->Release(); } MyWaitForRundownProtectionRelease(); } } 调用到深度3时,您基本上会返回所有教师,因为没有应用于加载查询的模式匹配将其限制为您正在谈论的节点。因此,从深度的角度考虑这个问题并不能真正帮助你做什么。

有两种(虽然类似)方法可以实现这一目标。

a)您正确地提到使用自定义session.loadAll。这是最简单的方法,您无需指定深度。为了使查询正常工作,您必须也返回您的关系。你的签名是这样的:

@Query

b)您可以使用 @Query("MATCH (t:Teacher)-[teacherRels:TEACHES]-(st:Student)-[studentRels:ATTENDS]-(su:Subject)-[subjectRels:REQUIRES]-(b:Book) WHERE ID(t) in {ids} RETURN t, teacherRels, st, studentRels, su, subjectRels, b") public Iterable<Teacher> findTeachersByIds(@Param("ids") List<Long> ids); 执行与上述相同的操作(这是上述方法基本上会调用的内容)。

如果你想升级,你应该使用session.query,这应该在2016年11月28日发布(如果你愿意,可以同时使用4.2.0.RC1。它比{{更稳定} 1}})。