当我调用
时,Neo4j Java API会自动将过时的数据库更新为当前版本 new GraphDatabaseFactory().newEmbeddedDatabase(File storeDir)
我想在执行此操作之前检查数据库的版本。有没有办法用Java API做到这一点?或者:存储数据库版本在哪里,以便我可以手动读出它?
答案 0 :(得分:1)
发布版本
我挖掘了Neo4j API源并找到了答案。 Neo4j从debug.log
目录中的logs
文件中读出以前的版本。每当启动数据库时,版本都会以Kernel version: (this is where you'll find the version)
的形式打印到日志文件中。例如,它看起来像这样:
2017-11-21 06:21:43.460+0000 INFO [o.n.k.i.DiagnosticsManager] Kernel version: 3.3.0,5b700972242a5ec3e0140261120f2845fb3520ad
你可以用Neo4j方式读出debug.log:
import java.io.File;
import org.neo4j.io.fs.DefaultFileSystemAbstraction;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.impl.transaction.log.LogTailScanner;
import org.neo4j.kernel.impl.transaction.log.PhysicalLogFile;
import org.neo4j.kernel.impl.transaction.log.PhysicalLogFiles;
import org.neo4j.kernel.impl.transaction.log.ReadableClosablePositionAwareChannel;
import org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader;
import org.neo4j.kernel.impl.transaction.log.entry.LogEntryVersion;
import org.neo4j.kernel.impl.transaction.log.entry.VersionAwareLogEntryReader;
public class Neo4jVersionChecker {
//Note that this method needs the store directory NOT the debug.log file
public static String getNeo4jVersion(File storeDir) {
FileSystemAbstraction fileSystem = new DefaultFileSystemAbstraction();
final PhysicalLogFiles logFiles = new PhysicalLogFiles( storeDir, PhysicalLogFile.DEFAULT_NAME, fileSystem );
final LogEntryReader<ReadableClosablePositionAwareChannel> logEntryReader = new VersionAwareLogEntryReader<>();
LogTailScanner tailScanner = new LogTailScanner( logFiles, fileSystem, logEntryReader );
LogEntryVersion version = tailScanner.getTailInformation().latestLogEntryVersion;
if(version!=null) {
return version.toString();
} else {
return null;
}
}
}
上述方法会为V3_0_10
返回debug.log
,其中Kernel version
条目的最新值为Kernel version
。
不幸的是,Neo4j方式不是很精确。您可以看到debug.log
中的3.3.0
以V3_0_10
开头,但Neo方法显示为import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.input.ReversedLinesFileReader;
public class VersionChecker {
public static String getVersion(File storeDir) {
File debugLog = new File(storeDir, "logs" + File.separator + "debug.log");
if(debugLog.exists()) {
try {
//The ReversedLinesFileReader reads the last line of a file first and so on
ReversedLinesFileReader reader = new ReversedLinesFileReader(debugLog, StandardCharsets.UTF_8);
//Read last line
String line = reader.readLine();
while(line!=null) {
//Line can't be null at this point
if(line.contains("Kernel version: ")) {
//This line contains the version
line = line.substring(line.indexOf("Kernel version: ")).substring(16); //get rid of everything except the version
line = line.split(",")[0]; //get rid of the second part of the Kernel version that we don't want
return line;
}
//Next line
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
。我假设这与Neo在内部处理版本的方式有关。
但是既然我们现在知道Neo4j如何获得版本,我们可以更准确地做同样的事情:
3.3.0
上述方法将返回neostore
。
商店版
当然,只有存在debug.log文件时,这两种方法才有效。并非所有以前的Neo4j版本都有它们。只要商店目录包含store version
文件,您就可以读出StoreVersionCheck
,这不如读取发行版本那么好,但至少它是一些东西。所以这是如何工作的:
有一个名为getVersion(File neostoreFile)
的Neo4j类,它包含一个非常方便的方法PageCache
。不幸的是,我们需要一个名为StoreVersionCheck
的实例来初始化PageCache
的实例。我们可以制作import java.io.File;
import java.io.IOException;
import java.util.Optional;
import java.util.function.Consumer;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.io.fs.DefaultFileSystemAbstraction;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory;
import org.neo4j.kernel.impl.pagecache.ConfiguringPageCacheFactory;
import org.neo4j.kernel.impl.storemigration.StoreVersionCheck;
import org.neo4j.kernel.impl.util.Neo4jJobScheduler;
import org.neo4j.kernel.monitoring.Monitors;
import org.neo4j.kernel.monitoring.tracing.Tracers;
import org.neo4j.logging.Log;
import org.neo4j.logging.Logger;
import org.neo4j.scheduler.JobScheduler;
public class StoreVersionChecker {
public static String getStoreVersion(File storeDir) {
File storeFile = new File(storeDir, "neostore");
if(!storeFile.exists()) {
return null;
}
StoreVersionCheck check = new StoreVersionCheck(buildPageCache());
try {
Optional<String> version = check.getVersion(storeFile);
if(version.isPresent()) {
return version.get();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static PageCache buildPageCache() {
FileSystemAbstraction fileSystem = new DefaultFileSystemAbstraction();
Config config = Config.defaults();
Log pageCacheLog = new DummyLog();
String desiredImplementationName = config.get( GraphDatabaseFacadeFactory.Configuration.tracer );
Monitors monitors = new Monitors();
JobScheduler jobScheduler = new Neo4jJobScheduler();
Tracers tracers = new Tracers( desiredImplementationName, new DummyLog(), monitors, jobScheduler );
ConfiguringPageCacheFactory pageCacheFactory = new ConfiguringPageCacheFactory(fileSystem, config, tracers.pageCacheTracer, tracers.pageCursorTracerSupplier, pageCacheLog );
PageCache pageCache = pageCacheFactory.getOrCreatePageCache();
if ( config.get( GraphDatabaseSettings.dump_configuration ) )
{
pageCacheFactory.dumpConfiguration();
}
return pageCache;
}
//We need this so we can give the Tracers a Log
private static class DummyLog implements Log {
@Override
public boolean isDebugEnabled() {return false;}
@Override
public Logger debugLogger() {return null;}
@Override
public void debug(String message) {}
@Override
public void debug(String message, Throwable throwable) {}
@Override
public void debug(String format, Object... arguments) {}
@Override
public Logger infoLogger() {return null;}
@Override
public void info(String message) {}
@Override
public void info(String message, Throwable throwable) {}
@Override
public void info(String format, Object... arguments) {}
@Override
public Logger warnLogger() {return null;}
@Override
public void warn(String message) {}
@Override
public void warn(String message, Throwable throwable) {}
@Override
public void warn(String format, Object... arguments) {}
@Override
public Logger errorLogger() {return null;}
@Override
public void error(String message) {}
@Override
public void error(String message, Throwable throwable) {}
@Override
public void error(String format, Object... arguments) {}
@Override
public void bulk(Consumer<Log> consumer) {}
}
}
,这就是我们要做的。
using (MuseumDBEntities db = new MuseumDBEntities())
{
db.Database.ExecuteSqlCommand("truncate table childTable");
db.Database.ExecuteSqlCommand("truncate table parentTable");
}