Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use H2 databases with a custom file extension?

Tags:

java

database

h2

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.

like image 379
stuXnet Avatar asked Mar 09 '15 10:03

stuXnet


People also ask

How do I read a H2 db file?

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 .

How do I access my H2 memory database?

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 .

How do I connect my H2 database to Chrome?

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.


1 Answers

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

like image 133
Andrey Avatar answered Nov 11 '22 19:11

Andrey