I'm building an application which stores its data in H2 database files, so my save files have the extension .h2.db
.
When opening the application, the user has to select which save file should be loaded. To make it easier to recognize these files, is it possible to tell H2 to use custom file extensions?
Looking at the Database URL overview of H2, I can only specify the name of the database. I would prefer a extension like .save
over the default .h2.db
. Is there a reasonable way to achieve this?
A workaround would be to link the *.save
-file to a temporary folder, renaming it to the correct suffix. If this is the only solution, I guess I would go with the default extension.
Alternatively you can connect using the browser based H2 console. The easiest way to access the console is to double click the H2 database jar file at <installation-directory>\confluence\WEB-INF\lib\h2-x.x.x.jar .
To access an in-memory database from another process or from another computer, you need to start a TCP server in the same process as the in-memory database was created. The other processes then need to access the database over TCP/IP or TLS, using a database URL such as: jdbc:h2:tcp://localhost/mem:db1 .
By default, the console view of the H2 database is disabled. Before accessing the H2 database, we must enable it by using the following property. Once we have enabled the H2 console, now we can access the H2 console in the browser by invoking the URL http://localhost:8080/h2-console.
H2 database supports pluggable file system so with a bit of extra code you can use any extension you want. You just need to create a wrapper, register it and use your own database URL. The wrapper could look like this:
package my.test;
import org.h2.store.fs.FilePath;
import org.h2.store.fs.FilePathWrapper;
public class FilePathTestWrapper extends FilePathWrapper {
private static final String[][] MAPPING = {
{".h2.db", ".save"},
{".lock.db", ".save.lock"}
};
@Override
public String getScheme() {
return "save";
}
@Override
public FilePathWrapper wrap(FilePath base) {
// base.toString() returns base.name
FilePathTestWrapper wrapper = (FilePathTestWrapper) super.wrap(base);
wrapper.name = getPrefix() + wrapExtension(base.toString());
return wrapper;
}
@Override
protected FilePath unwrap(String path) {
String newName = path.substring(getScheme().length() + 1);
newName = unwrapExtension(newName);
return FilePath.get(newName);
}
protected static String wrapExtension(String fileName) {
for (String[] pair : MAPPING) {
if (fileName.endsWith(pair[1])) {
fileName = fileName.substring(0, fileName.length() - pair[1].length()) + pair[0];
break;
}
}
return fileName;
}
protected static String unwrapExtension(String fileName) {
for (String[] pair : MAPPING) {
if (fileName.endsWith(pair[0])) {
fileName = fileName.substring(0, fileName.length() - pair[0].length()) + pair[1];
break;
}
}
return fileName;
}
}
Then you'll need to register it:
FilePathTestWrapper wrapper = new FilePathTestWrapper();
FilePath.register(wrapper);
And use database URL like this:
"jdbc:h2:save:./mydatabase"
Note the "save:" prefix, it should match string returned by getScheme() method. I put a bit more details here: http://shuvikov.net/blog/renaming-h2-database-files
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With