Create an Access database file (.mdb or .accdb) using Java - java

Currently I have one application in which I am able to access .mdb or .accdb
file with JdbcOdbcDriver to append some data.
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection("jdbc:odbc:MsAccessDSN");
but in this, I need to configure System DSN. We need to add new Data Source (Microsoft Access Driver) and then need to provide location of .mdb file. Only then above code will work.
Suppose I want to run my application on other system then I need to do same thing to that computer.
If I give my application to the client and he/she don't know how to configure .mdb file. Then my whole effort will waste.
So any driver is available by which I create .mdb file by my Java Code and then append all the data into the table of .mdb file.
Or is there any other way, where Java code can create .mdb file and able to access this database file.
I tried this code which append data without configuring System DNS:
public class TestMsAccess {
private static Connection con;
private static Statement stm;
private static String tableName = "EmpDetail";
private static int id_is = 2;
private static String name_is = "Employee1";
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=D:\\MSAccessProject/Employee.mdb", "", "");
stm = con.createStatement();
// enter value into table
String addRow = "INSERT INTO " + tableName + " VALUES ( "
+ id_is + ", '"
+ name_is + "')";
stm.execute(addRow);
if (con != null) { con.close(); }
if (stm != null) { stm.close(); }
}
}
But the problem is, this code not create .mdb file automatically but work when I create .mbd file and table before running this code.

Update for Jackcess 2.x: Databases are now created (or opened) using DatabaseBuilder, so to create a new database file we do
import java.io.File;
import java.io.IOException;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Database.FileFormat;
import com.healthmarketscience.jackcess.DatabaseBuilder;
public class JackcessDemoMain {
public static void main(String[] args) {
String dbPath = "C:/Users/Public/newDb.accdb";
// using try-with-resources is recommended to ensure that
// the Database object will be closed properly
try (Database db = DatabaseBuilder.create(FileFormat.V2010, new File(dbPath))) {
System.out.println("The database file has been created.");
} catch (IOException ioe) {
ioe.printStackTrace(System.err);
}
}
}
Original answer for Jackcess 1.x (deprecated):
If you would like to create the “.mdb” file through java, you can use the Jackcess Java library which is one of the pure Java Library for reading from and writing to MS Access databases. Currently supporting versions include 2000-2007 I guess. Please have a look at the below example for better understanding:
Download Jackcess Java library (jackcess-1.2.6.jar)
from http://jackcess.sourceforge.net/
and commons-logging-1.1.jar
from http://commons.apache.org/logging/download_logging.cgi
and commons-lang-2.0.jar
from http://www.findjar.com/index.x?query=commons-lang
Add both jars to your classpath.
Try the below code to create a database automatically:
package com.jackcess.lib;
import com.healthmarketscience.jackcess.ColumnBuilder;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.TableBuilder;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
/**
*
* #author sarath_ivan
*/
public class JackcessLibrary {
private static Database createDatabase(String databaseName) throws IOException {
return Database.create(new File(databaseName));
}
private static TableBuilder createTable(String tableName) {
return new TableBuilder(tableName);
}
public static void addColumn(Database database, TableBuilder tableName, String columnName, Types sqlType) throws SQLException, IOException {
tableName.addColumn(new ColumnBuilder(columnName).setSQLType(Types.INTEGER).toColumn()).toTable(database);
}
public static void startDatabaseProcess() throws IOException, SQLException {
String databaseName = "C:/Users/compaq/Desktop/employeedb.mdb"; // Creating an MS Access database
Database database = createDatabase(databaseName);
String tableName = "Employee"; // Creating table
Table table = createTable(tableName)
.addColumn(new ColumnBuilder("Emp_Id").setSQLType(Types.INTEGER).toColumn())
.addColumn(new ColumnBuilder("Emp_Name").setSQLType(Types.VARCHAR).toColumn())
.addColumn(new ColumnBuilder("Emp_Employer").setSQLType(Types.VARCHAR).toColumn())
.toTable(database);
table.addRow(122875, "Sarath Kumar Sivan","Infosys Limited.");//Inserting values into the table
}
public static void main(String[] args) throws IOException, SQLException {
JackcessLibrary.startDatabaseProcess();
}
}

Now that the JDBC-ODBC Bridge has been removed from Java (as of Java 8), future readers might be interested in UCanAccess, a free and open-source pure Java JDBC driver for Access databases. UCanAccess includes a newdatabaseversion connection parameter that will create the Access .accdb or .mdb file if it does not already exist.
Sample code:
String dbFileSpec = "C:/Users/Gord/Desktop/myDb.accdb";
try (Connection conn = DriverManager.getConnection(
"jdbc:ucanaccess://" + dbFileSpec +
";newdatabaseversion=V2010")) {
DatabaseMetaData dmd = conn.getMetaData();
try (ResultSet rs = dmd.getTables(null, null, "Clients", new String[] { "TABLE" })) {
if (rs.next()) {
System.out.println("Table [Clients] already exists.");
} else {
System.out.println("Table [Clients] does not exist.");
try (Statement s = conn.createStatement()) {
s.executeUpdate("CREATE TABLE Clients (ID COUNTER PRIMARY KEY, LastName TEXT(100))");
System.out.println("Table [Clients] created.");
}
}
}
conn.close();
}
For details on how to set up UCanAccess see
Manipulating an Access database from Java without ODBC

download jackcess library
use this library whcih will create .mdb file.Bellow is the code snipet
download jackcess libraries from above location. add required jar file in class path.
`
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import com.healthmarketscience.jackcess.ColumnBuilder;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.TableBuilder;
public class MDBFileGenerator {
public static void main(String[] args) throws IOException, SQLException {
Database db = DatabaseBuilder.create(Database.FileFormat.V2000,
new File("new.mdb"));
Table newTable = new TableBuilder("NewTable")
.addColumn(new ColumnBuilder("a").setSQLType(Types.INTEGER))
.addColumn(new ColumnBuilder("b").setSQLType(Types.VARCHAR))
.toTable(db);
newTable.addRow(1, "foo");
}
}
`

You can use the below method instead of configuring System DSN in your machine.
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
connection = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:/Users/Desktop/your-database-file.mdb", "", "");
Here "your-database-file.mdb" is your MS-Access file. You can give the full path of your database file in your code to establish the connection. You can also keep the database file in your project(application) folder. In this case you will be able to give your database file along with the application to the client and he/she can use your application without anymore DSN configuration.
Hope this serves your purpose!
Thanks you!

It looks like there is at least one option for connecting directly to .mdb without the JdbcOdbcDriver, that that option is commercial. See here. If the setup is what you're trying to avoid, have you considered using something an embedded database like sqlite?

Related

Best way to connect java swing app to ms access db on a shareserver?

Currently im developing a java swing application that I'd like to serve as the GUI for CRUD operations on a MS access database. Currently, everyone on the team that will be using this application updates a spreadsheet on a shareserver. They'd like to switch over to a UI that better suits their purposes, and transition the spreadsheet to a database.
I'm planning on putting an executable jar and the ms access database file on the shareserver. This is where the jar will be accessed.
I don't want users to have to be messing with ODBC settings. Is there a library that can help with this?
UPDATE: Shailendrasingh Patil's suggestion below worked best for me. This took me a little bit of research and the setup was a bit confusing. But I eventually got everything working the way I was hoping. I used Gradle to pull in the necessary dependencies to use UcanAccess.
The following is a snippet from my DatabaseController class:
import javax.swing.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class DatabaseController {
public DatabaseController() {}
public void addOperation(String date, String email, String subject, String body) {
try{
Connection con = DriverManager.getConnection("jdbc:ucanaccess://C:\\Users\\user\\Desktop\\TestDatabase.accdb;jackcessOpener=CryptCodecOpener","user", "password");
String sql = "INSERT INTO Email (Date_Received, Email_Address, Subject, Message) Values " +
"('"+date+"'," +
"'"+email+"'," +
"'"+subject+"'," +
"'"+body+"')";
Statement statement = con.createStatement();
statement.execute(sql);
}
catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(),"Error",
JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
}
}
The following class is also required:
import java.io.File;
import java.io.IOException;
import com.healthmarketscience.jackcess.CryptCodecProvider;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import net.ucanaccess.jdbc.JackcessOpenerInterface;
public class CryptCodecOpener implements JackcessOpenerInterface {
public Database open(File fl,String pwd) throws IOException {
DatabaseBuilder dbd =new DatabaseBuilder(fl);
dbd.setAutoSync(false);
dbd.setCodecProvider(new CryptCodecProvider(pwd));
dbd.setReadOnly(false);
return dbd.open();
}
}
I apologize for the bad indentations.
You should use UCanAccess drivers to connect to MS-Access. It is a pure JDBC based and you don't need ODBC drivers.
Refer examples here

NonWritableChannelException when trying to update an Access database

Using UCanAccess for the first time for a project and I am having a lot of trouble inserting a row into one of my database tables (in Microsoft Access).
My code makes sense but once I execute I end up getting the same error every time, even though NetBeans is able to connect to my database.
package Vegan;
import java.sql.Connection;
import java.sql.DriverManager;
public class connectionString {
static Connection connection = null;
public static Connection getConnection()
{
try
{
connection = DriverManager.getConnection("jdbc:ucanaccess://C://MyDatabase1.accdb");
System.out.println("---connection succesful---");
}
catch (Exception ex)
{
System.out.println("Connection Unsuccesful");
}
return connection;
}
package Vegan;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class DB {
private static ResultSet rs = null;
private static PreparedStatement ps = null;
private static Connection connection = null;
public DB() {
connection = connectionString.getConnection();
}
public void AddTest() {
try {
String sql = "INSERT INTO CategoryTbl(CategoryName) VALUES (?)";
ps = connection.prepareStatement(sql);
ps.setString(1, "Flours");
ps.executeUpdate();
System.out.println("Inserted");
} catch (Exception ex) {
System.out.println(ex.getLocalizedMessage().toString());
}
}
After that, when I execute the the AddTest() method, I get this system output:
run:
---connection succesful---
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:724)
at com.healthmarketscience.jackcess.impl.PageChannel.writePage(PageChannel.java:297)
UCAExc:::3.0.6 null
at com.healthmarketscience.jackcess.impl.PageChannel.writePage(PageChannel.java:234)
at com.healthmarketscience.jackcess.impl.TableImpl.writeDataPage(TableImpl.java:1375)
at com.healthmarketscience.jackcess.impl.TableImpl.addRows(TableImpl.java:1624)
at com.healthmarketscience.jackcess.impl.TableImpl.addRow(TableImpl.java:1462)
at net.ucanaccess.converters.UcanaccessTable.addRow(UcanaccessTable.java:44)
at net.ucanaccess.commands.InsertCommand.insertRow(InsertCommand.java:101)
at net.ucanaccess.commands.InsertCommand.persist(InsertCommand.java:148)
at net.ucanaccess.jdbc.UcanaccessConnection.flushIO(UcanaccessConnection.java:315)
at net.ucanaccess.jdbc.UcanaccessConnection.commit(UcanaccessConnection.java:205)
at net.ucanaccess.jdbc.AbstractExecute.executeBase(AbstractExecute.java:161)
at net.ucanaccess.jdbc.ExecuteUpdate.execute(ExecuteUpdate.java:50)
at net.ucanaccess.jdbc.UcanaccessPreparedStatement.executeUpdate(UcanaccessPreparedStatement.java:253)
at Vegan.DB.AddTest(DB.java:91)
at Vegan.TestDB.main(TestDB.java:17)
BUILD SUCCESSFUL (total time: 1 second)
With no changes being made to the database when I check on it again Access.
What could be causing this, and what does the error message mean? Thank you
"java.nio.channels.NonWritableChannelException" means that the database file cannot be updated. In your case that was because the database file was in the root folder of the Windows system drive (C:\) and mere mortals have restricted permissions on that folder.
Solution: Move the database file to a folder where you have full write access.

Im trying to insert a rows in sqlite embedded db in java. after inserting changes are visible in that program alone

I'm trying to insert rows in SQLite embedded DB in java. after adding changes are visible in that program alone. I can't see the changes in sqlite manager. When I try to insert a row in sqlite manager values that inserted which are shown in the program gets deleted. And showing those row that I added using sqlite manager. Please help..
connection class
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
public class HsqlConn {
//public static void main(String[] args) {
public static Connection hconn = null;
public static Statement hstmt = null;
public static PreparedStatement pst = null;
public static void hConnectDb(){
try{
Class.forName("org.sqlite.JDBC");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL resource = classLoader.getResource("PS/PSDB.sqlite");
hconn = DriverManager.getConnection("jdbc:sqlite::resource:"+resource);
}
catch(Exception se){
//Handle errors for JDBC
se.printStackTrace();
}
}
}
main class using that db
private void jButton8ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try{
hConnectDb();
String sql1 = "Insert into Bill (billNo,date,principal,principalText,custId,dueDate) values (?,?,?,?,?,?)";
pst = hconn.prepareStatement(sql1);
pst.setString(1,BillNoField.getText());
pst.setString(2,dateField1.getText());
pst.setString(3,PrincipalField.getText());
pst.setString(4,PrincipaTextField.getText());
pst.setString(5,custIdField.getText());
pst.setString(6,dueDateField.getText());
pst.executeUpdate();
pst.close();
hconn.close();
JOptionPane.showMessageDialog(null, "saved");
}
catch(Exception e){
JOptionPane.showMessageDialog(null, e);
}
}
According to the documentation of sqlite-jdbc, connection URL strings beginning with "jdbc:sqlite::resource:" are for loading read-only SQLite databases:
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
You need to specify a file in the filesystem containing your SQLite database. On Windows, an example is:
Connection connection = DriverManager.getConnection("jdbc:sqlite:C:/work/mydatabase.db");
and on UNIX-like systems, an example is:
Connection connection = DriverManager.getConnection("jdbc:sqlite:/home/leo/work/mydatabase.db");

How to use Java Property File?

I need to use .properties file in Java to store database information.
Here is my database connector class. It's giving NullPointerException. What is the issue with my code ?
Note, that I haven't' assign those property file values. DB connection values are still hard coded.
import java.io.IOException;
import java.io.InputStream;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class Database {
public Connection connection;
private Statement statement;
private Properties property;
public static Database database;
private Database() {
String url = "jdbc:mysql://localhost:3306/";
String dbName = "edus";
String driver = "com.mysql.jdbc.Driver";
String userName = "root";
String password = "";
try {
InputStream is = Database.class.getClassLoader().getResourceAsStream(
"config.properties");
property.load(is);
System.out.println(property.getProperty("db_user"));
System.out.println(property.getProperty("db_password"));
System.out.println(property.getProperty("db_name"));
Class.forName(driver).newInstance();
this.connection = (Connection) DriverManager.getConnection(url + dbName,
userName, password);
}catch (IOException ex) {
Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException e) {
System.out.println("JDBC driver is missing");
} catch (InstantiationException | IllegalAccessException | SQLException e) {
e.printStackTrace();
}
}
public static synchronized Database getDatabaseConnection() {
if (database == null) {
database = new Database();
}
return database;
}
}
config.properties is not lying under classpath. It should be under classes folder.
you can also try
Database.class.getClassLoader().getResourceAsStream(
"com/lk/apiit/eduservice/config.properties");
As Roman C pointed out you also need to initialize Properties Object first
Properties property = new Properties();
You forgot to initialize
Properties property = new Properties();
This is an issue of NullPointerException in your code, because you referenced not initialized variable.
If you open a stream you should close it after it's not used. Do it by adding finally block.
The code where you getting a connection to the database you can move to the corresponding method. If the connection is closed you will not reinitialize the database again just reopen a connection or get a new one.
Dont keep config properties file in a package. Keep it directly inside the source folder, so that the config properties file comes directly in the build/classes folder after the build is done.
The issue is that your config properties in in the folder com/ik/apiit/eduservice folder but your code is expecting it to be directly in the classes folder (the root folder of classpath).
try this
FileInputStream in = new FileInputStream(System.getProperty("WEB-INF/dbConnection.properties"));
prop.load(in);

How to run this .java file in a web-app as a solo java application just to test it?

package database;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import database.Dbconnect;
public class CreateQuery {
Connection conn;
/**
* #throws ClassNotFoundException
* #throws SQLException
* #throws IOException
*/
public CreateQuery() throws ClassNotFoundException, SQLException, IOException {
conn=new Dbconnect().returnDatabaseConnection();
}
public int addNewLayertoDB(String feature_name,String shape,int Latitude , int Longitude , int feature_geom , String feature_details){
try {
PreparedStatement statement = null;
String table_name = feature_name + "_" + shape;
String query = "CREATE TABLE EtherMap "+table_name+" ("+ feature_name+" (20))";
statement = conn.prepareStatement(query);
statement.setString(1, feature_name);
statement.execute();
String squery = "ALTER TABLE EtherMap" +table_name+" ADD COLUMN geom int , ADD COLUMN shape character(10)";
return 1;
} catch (SQLException ex) {
return 0;
}
}
public void closeConn() throws SQLException {
if (conn != null) {
this.conn.close();
}
}
}
I want to test this java code to see if anything is being updated in the postgresql database .
How do I do this in ecclipse IDE ?
There is nothing in this code that requires it to be in a web-app.
That's a good thing, as web-apps are components of their Servlet containers. In other words, you can't really run a standalone web-app, you must deploy it. Perhaps you'll deploy it in a micro-container that only contains your application, but there's nothing like true stand-alone running of a component.
In your case, just add a public static void main(String[] args) { to this code, put the desired calls to create the class and perform the operations, and give it a spin. If it's not just a "quick check" but a formal test that might be repeated, look into JUnit.
I would suggest writing a TestCase and making sure (assert)that the data you store in postgres, you can read it.

Categories