I have the following question which is keeping me busy for some time now.
I am building a Java project in Netbeans and I have an embedded sqlite DB which I use in this project.
Currently the DB is located in the package src/release/.
I reference the db from the code the following way:
c = DriverManager.getConnection("jdbc:sqlite:src/release/db.db3");
When I run the project from within Netbeans it works without any problem. But when I try to build it and run the created jar-file (in the dist-folder).
I get the following error message (translated from Dutch description):
Opening connection failed: path to
scr/release/db.db3:'C:\users\idxxxxx\Documents\\dist\src'
does not exist
When referencing the DB in the code like this:
c = driverManager.getConnection("jdbc:sqlite:db.db3");
and adding the db-file to the root of the output-dir (so not in the jar itself), the application works partly, but some db-data is missing in my application (empty comboboxes).
So there seems to be an issue also.
My question is:
How can I add an embedded db - sqlite in this case - in netbeans to my project so it will be part of my project?
Where should I put the db-file and how do I reference it from within my project-code?
I don't want the enduser to see any db-file in the file(s) he will receive.
so I would like the db-file to be part of the .jar if possible.
Tnx
SQLite needs separate files, even without the need to update the database.
Need ensures locking and ensures database ACID properties.
SQLite from inside .jar
SQLite is designed to work with direct file access.
SQLite may require additional privileges not available in some environments.
The SQLite data files could be extracted from the JAR to a temporary location at start.
It is not a good choice to write the database url, directly into the program.
getConnection("jdbc:sqlite:src/release/db.db3");
Let your application look for the file. If not found: error: File db.db3 not found message. Then know the user, not the program is going wrong, but it is missing the database file.
Since you are working with java, it is easy to create dynamic url.
e.g. "jdbc:sqlite:"+PathToApp +"/data/db.db3".
Then the application knows where to copy the extracted file (db.db3 from the jar ) .
extract SQlite from .jar
You can let java doing it for you.
Use jdbc:sqlite::resource:
you need the sqlite-jdbc JAR, so extract the JAR file and add into the application JAR.
DB files will be extracted to a temporary folder System.getProperty(“java.io.tmpdir”).
e.g.
[...]
import org.sql.*;
import org.sqlite.*;
[...]
try {
Class.forName("org.sqlite.JDBC");
SQLiteConfig config = new SQLiteConfig();
config.enableFullSync(true);
config.setReadOnly(false);
SQLiteDataSource ds = new SQLiteDataSource(config);
ds.setUrl("jdbc:sqlite::resource:"+
getClass().getResource("db.db3").toString());
conn = ds.getConnection();
}catch(SQLException se)
{
System.out.println("SQLError: "...");
}
Update oct. 2014
org.sqlite SQLiteConfig + SQLiteDataSource
2014 October 8th: sqlite-jdbc-3.8.6.jar Updated to sqlite 3.8.6
Related
I've requirement to create database once with create/insert statements and then make it available inside javafx runnable jar with read only DB access.
I just gone through H2 database document many time and tried to achieve this using H2 Driver version 1.4.196 and 1.4.192 but I think I'm missing something.
I can connect without including it into runnable jar and read only things works as well. But I need to access it from jar itself to prevent DB access from outsiders.
Can I've connection string or logic to connect read only DB file from jar itself ?
Ofcourse I need more clear practical example from this, this and this.
I've implemented zipping logic as this and it works fine from given path.
But when I've added zip file in runnable jar and accessing it through following code:
DriverManager.getConnection("jdbc:h2:file:split:zip:./test.zip!/test");
Then it throws exception with:
Exception in thread "main" org.h2.jdbc.JdbcSQLException: IO Exception: "java.io.FileNotFoundException: .\jar\res\buzdirectory.zip (The system cannot find the path specified)"; "listFiles zip:./jar/res/buzdirectory.zip!/" [90031-196]
If I put fully qualified path then it works well:
DriverManager.getConnection("jdbc:h2:file:split:zip:C:\\CoreJava\\src\\main\\java\\res\\test.zip!/test");
What I'm missing here to access it from jar file.
I think we cannot open the database file directly from the runnable JAR file. To access it should be a "real" file, so we will need to extract it from the JAR and then open that copy.
For example, to extract the database from the JAR into a temporary file:
File dbFile = File.createTempFile("temp", ".zip");
dbFile.deleteOnExit();
java.nio.file.Files.copy(this.getClass().getResourceAsStream("/db/temp.zip"),
dbFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
StringBuffer connStr = new StringBuffer("jdbc:h2:file:split:zip:")
.append(dbFile.getAbsolutePath()).append("!/temp");
Connection conn = DriverManager.getConnection(connStr.toString());
conn.close();
System.out.println("closed");
By the way this is not preferable approach yet all. But we can use this kind of approach in some special cases.
So I'm new to working with Java databases and I've settled on using Apache Derby. I have it installed on my system and have included the derby.jar in the project buildpath. However, I need this project to be portable (including from Windows to OSX/UNIX) so that the database can be initialized and fully accessed for updating and reading on a device other than my machine.
So my question is, how do I make this happen? Is including the derby.jar file enough or do I need to do something like initialize a database within the project file system or something else? Do I need to specify a certain write location in a class within the project? If it's helpful, I'm using Eclipse IDE.
Thanks for any help!
So after some thorough reading I found my own solution, at least in theory (I've not yet finished the project build to try it out). Use this in a Data Access Object (DAO).
As per John O'Conner:
private void setDBSystemDir() {
/* Decide on the db system directory: <userhome>/DerbyDB/DBName/ */
String userHomeDir = System.getProperty("user.home", ".");
String systemDir = userHomeDir + "/DerbyDB/DBName";
// Set the db system directory.
System.setProperty("derby.system.home", systemDir);
}
I have the following question which is keeping me busy for some time now.
I am building a Java project in Netbeans and I have an embedded sqlite DB which I use in this project.
Currently the DB is located in the package src/release/.
I reference the db from the code the following way:
c = DriverManager.getConnection("jdbc:sqlite:src/release/db.db3");
When I run the project from within Netbeans it works without any problem. But when I try to build it and run the created jar-file (in the dist-folder).
I get the following error message (translated from Dutch description):
Opening connection failed: path to
scr/release/db.db3:'C:\users\idxxxxx\Documents\\dist\src'
does not exist
When referencing the DB in the code like this:
c = driverManager.getConnection("jdbc:sqlite:db.db3");
and adding the db-file to the root of the output-dir (so not in the jar itself), the application works partly, but some db-data is missing in my application (empty comboboxes).
So there seems to be an issue also.
My question is:
How can I add an embedded db - sqlite in this case - in netbeans to my project so it will be part of my project?
Where should I put the db-file and how do I reference it from within my project-code?
I don't want the enduser to see any db-file in the file(s) he will receive.
so I would like the db-file to be part of the .jar if possible.
Tnx
SQLite needs separate files, even without the need to update the database.
Need ensures locking and ensures database ACID properties.
SQLite from inside .jar
SQLite is designed to work with direct file access.
SQLite may require additional privileges not available in some environments.
The SQLite data files could be extracted from the JAR to a temporary location at start.
It is not a good choice to write the database url, directly into the program.
getConnection("jdbc:sqlite:src/release/db.db3");
Let your application look for the file. If not found: error: File db.db3 not found message. Then know the user, not the program is going wrong, but it is missing the database file.
Since you are working with java, it is easy to create dynamic url.
e.g. "jdbc:sqlite:"+PathToApp +"/data/db.db3".
Then the application knows where to copy the extracted file (db.db3 from the jar ) .
extract SQlite from .jar
You can let java doing it for you.
Use jdbc:sqlite::resource:
you need the sqlite-jdbc JAR, so extract the JAR file and add into the application JAR.
DB files will be extracted to a temporary folder System.getProperty(“java.io.tmpdir”).
e.g.
[...]
import org.sql.*;
import org.sqlite.*;
[...]
try {
Class.forName("org.sqlite.JDBC");
SQLiteConfig config = new SQLiteConfig();
config.enableFullSync(true);
config.setReadOnly(false);
SQLiteDataSource ds = new SQLiteDataSource(config);
ds.setUrl("jdbc:sqlite::resource:"+
getClass().getResource("db.db3").toString());
conn = ds.getConnection();
}catch(SQLException se)
{
System.out.println("SQLError: "...");
}
Update oct. 2014
org.sqlite SQLiteConfig + SQLiteDataSource
2014 October 8th: sqlite-jdbc-3.8.6.jar Updated to sqlite 3.8.6
I am using JAVA (with eclipse juno) and try to create an executable JAR file which include sqlite DB file.
I've try to get connection to the DB by this line:
DriverManager.getConnection("jdbc:sqlite:"+DataController.class.getResource("test.sqlite").getPath())
The DataController is a class that located where the sqlite located.
and i keep get an error:
java.sql.SQLException: invalid database address
Does someone can help and give step by step instructions about how to include sqlite DB inside an executable JAR file?
Apparently sqlite-jdbc can open resources on it's own. Per this thread https://groups.google.com/forum/?fromgroups=#!topic/xerial/Oayzj5nrJGk, add :resource to the path. So try the following:
DriverManager.getConnection("jdbc:sqlite::resource:package/test.sqlite");
or depends on version of sqlite
DriverManager.getConnection("jdbc:sqlite::resource:package/test.db");
Replacing package with the '/' separated path to the package this file is in.
Be aware that it will actually copy the file to a tmp directory.-
The ::resource way is right. And these explanations will help if you are using ::resource but still get errors like resource database.db not found: java.net.MalformedURLException: no protocol: database.db like verdana.
Most common anwsers are:
DriverManager.getConnection("jdbc:sqlite::resource:path/to/database.db")
However the path/to/database.db must be the exact path(the Path in Real File System but not in Jar) to your jar file.
I recommend to use getClass().getResource():
DriverManager.getConnection("jdbc:sqlite::resource:" +
getClass().getResource("/path/to/db/in/the/jar/file"))
NOTE:the /path/to/db/in/the/jar/file part must start with /
I'm not sure if this has changed in recent JDBC versions, but after fiddling with it for about an hour and getting various exceptions (MalformedURLException and "Database has been closed"), I found that the following worked for me:
DriverManager.getConnection("jdbc:sqlite::resource:file:/path/to/database.db")
The :file: portion seems to be missing from other answers and I couldn't get it to work without it.
Also, note that the
/path/to/database.db
is the absolute path starting from the root of the .jar file, rather than a normal resource root.
jdbc:sqlite::resource:notes_app.db
worked for me. My database(notes_app.db) was in the root of generated jar file.
public class Database {
public static Connection con () throws SQLException {
String url = "jdbc:sqlite::resource:notes_app.db";
return DriverManager.getConnection(url);
}
}
My notes_app.db is in the root of generated jar. I'm developing with maven and notepadd++
I have created a Swing application that uses SQLite as a local database. The database file is located in project's root directory.
Project/DatabaseFile
The application runs fine on Eclipse, but when I run the packaged executable Jar, I get the following error:
No such table : table1
This means that the database is not reachable. When I examined the contents of the resulting JAR file, the database file was not there anymore.
In the code, I've linked the database as follows:
jdbc:sqlite:DatabaseFile
My question is, how to include the SQLite database in the executable Jar?
EDIT
When I placed the DB file in the source Folder Project/src/DatabaseFile and changed the path to jdbc:sqlite:src/DatabaseFile, it worked on Eclipse but again when running the Jar file as java -jar Project.jar. It said:
path to 'src/DatabaseFile': 'C:\Users\name\src' does not exist
I think I need to specify a relative path for the database.
EDIT
This is how I connect to the database:
public Connection getConnection(){
try{
Class.forName("org.sqlite.JDBC").newInstance();
con = DriverManager.getConnection("jdbc:sqlite:src/DatabaseFile");
} catch (Exception e) {
Log.fatal("Méthode: getConnection() | Class : SQLiteConnection | msg system : " + e.getMessage());
}
return con;
}
What library are you using for SQLite?
I did a search based on the connection URI you indicated and found this one. In the documentation it says:
2009 May 19th: sqlite-jdbc-3.6.14.1 released. This version supports "jdbc:sqlite::resource:" syntax to access read-only DB files contained in JAR archives, or external resources specified via URL, local files address etc. (see also the detailes)
If that is the driver you are using, then I would suggest the following connection URI:
"jdbc:sqlite::resource:DatabaseFile"
The key is that since your database is in a jar file, it can not be access as a file with FileInputStream. Instead it must be accessed through the JVM's support for it (namely with Class.getResource() or Class.getResourceAsStream()). Do note that resources contained within jar files are read-only. You won't be able to save any changes to your database.
I have found two different ways to name the filepath depending on how you are trying to access it. Assuming you are accessing the db is located in /yourproject/resource/ or /yourproject/bin/resource ( havent narrowed it down, mine is in both and I'm happy with it) you should use this as your path:
//Eclipse test path
String url = "jdbc:sqlite:resource/mydb.db";
or
//runnable jar path
String url = "jdbc:sqlite::resource:mydb.db";
then
mysqlitedatasource.setUrl(url);
Your way also works... by putting the db in /src