NonWritableChannelException when trying to update an Access database - java

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.

Related

In SQLite how to backup database from disk into memory using JDBC driver

I wanted to load SQLite database from disk to memory and I'm using JDBC driver, but I couldn't find any proper method in Java to do this.
JDBC Driver:
implementation group: 'org.xerial', name: 'sqlite-jdbc', version: '3.36.0.3'
I found that here, In python we can use below code to do that
import sqlite3
source = sqlite3.connect('existing_db.db')
dest = sqlite3.connect(':memory:')
source.backup(dest)
Is there any similar approach in Java also ?
Update - 1
I tried using restore command but even that didn't work
Connection connection =
DriverManager.getConnection("jdbc:sqlite:file:prod?mode=memory&cache=shared", config.toProperties());
Statement statement = connection.createStatement();
statement.executeUpdate("restore from products.db");
Update - 2
(In response to Answer by #Sergey Vyacheslavovich Brunov)
I'm attaching the code I used and it's output. If we see the Non-Heap Memory(Native Memory) usage there is no much increase, but also I was able to print the number of entries loaded (Output Section).
Now where are records getting loaded? Not able to track it
package com.example.sqlite.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.sqlite.SQLiteConfig;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
#Service
#Slf4j
public class CacheService {
private static Connection globalConnection = null;
public static Connection getConnection() {
return globalConnection;
}
public String buildCache() {
try {
SQLiteConfig config = new SQLiteConfig();
config.setPragma(SQLiteConfig.Pragma.JOURNAL_MODE, "wal");
config.setPragma(SQLiteConfig.Pragma.SYNCHRONOUS, "normal");
config.setPragma(SQLiteConfig.Pragma.TEMP_STORE, "memory");
globalConnection = DriverManager.getConnection("jdbc:sqlite:file::memory:?cache=shared",
config.toProperties());
try (
Connection connection = DriverManager.getConnection(
"jdbc:sqlite:file::memory:?cache=shared", config.toProperties());
Statement statement = connection.createStatement()
) {
statement.executeUpdate("restore from /Users/swastikn/Desktop/products.db");
ResultSet resultSet =
statement.executeQuery("SELECT COUNT(*) AS count FROM products_1");
log.info("Successfully loaded {} entries into Memory", resultSet.getInt("count"));
resultSet.close();
return "SUCCESS";
}
} catch (Exception e) {
log.error("Error while building cache: {}", e.getMessage());
}
return "ERROR";
}
}
Output
2022-07-09 13:23:10.741 INFO 2591 --- [nio-8081-exec-1] com.example.sqlite.service.CacheService : Successfully loaded 584524 entries into Memory
Non-Heap (Native Memory) Usage
Analysis
Could not reproduce the problem.
Just a guess. Please, make sure that the closeable resources (java.sql.Connection, java.sql.Statement, java.sql.ResultSet, etc.) are used and closed appropriately.
Working draft example program
Maven project (pom.xml)
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.36.0.3</version>
<scope>runtime</scope>
</dependency>
Program class
For the first run, please, apply the following changes:
Uncomment the forceSeed() method call.
Comment the restore() method call.
Afterwards, for the subsequent runs, please, undo these changes.
package info.brunov.stackoverflow.question72870080;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public final class Program {
public static void main(final String[] args) throws SQLException {
try (
final Connection connection = DriverManager.getConnection("jdbc:sqlite::memory:");
) {
// NOTE: Uncomment the below line for the first run:
// forceSeed(connection);
// NOTE: Comment the below line for the first run:
restore(connection);
printPersons(connection);
backup(connection);
}
}
private static void forceSeed(final Connection connection) throws SQLException {
try (final Statement statement = connection.createStatement()) {
statement.executeUpdate("DROP TABLE IF EXISTS person");
statement.executeUpdate("CREATE TABLE person (id integer, name string)");
statement.executeUpdate("INSERT INTO person VALUES(1, 'First')");
statement.executeUpdate("INSERT INTO person VALUES(2, 'Second')");
statement.executeUpdate("INSERT INTO person VALUES(3, 'Third')");
}
}
private static void printPersons(final Connection connection) throws SQLException {
try (
final Statement statement = connection.createStatement();
final ResultSet resultSet = statement.executeQuery("SELECT * FROM person");
) {
while (resultSet.next()) {
System.out.println(
String.format(
"Person: ID: %d, Name: %s.",
resultSet.getInt("id"),
resultSet.getString("name")
)
);
}
}
}
private static void backup(final Connection connection) throws SQLException {
try (final Statement statement = connection.createStatement()) {
statement.executeUpdate("BACKUP TO backup.db");
}
}
private static void restore(final Connection connection) throws SQLException {
try (final Statement statement = connection.createStatement()) {
statement.executeUpdate("RESTORE FROM backup.db");
}
}
}
Program output
Person: ID: 1, Name: First.
Person: ID: 2, Name: Second.
Person: ID: 3, Name: Third.

Java JDBC: Cannot insert Data into Database

I'm coding for hours to insert data into my SQL database, but nothing happens.
I even can't debug Java, because I don't get any output of my console.
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.PreparedStatement;
import java.text.DecimalFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author xxx
*/
public class MyServlet extends HttpServlet {
private static final String URL = "jdbc:mysql://localhost:3306/userdata";
private static final String USER = "root";
private static final String PASSWORD = "root";
private static final DecimalFormat DF2 = new DecimalFormat("#.##");
private static Connection con;
private static Statement stmt;
private static ResultSet rs;
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
try {
String myDriver = "com.mysql.jdbc.Driver";
try {
Class.forName(myDriver);
// opening database connection to MySQL server
con = DriverManager.getConnection(URL, USER, PASSWORD);
// getting Statement object to execute query
// the mysql insert statement
String query = "INSERT INTO customers (customer, currency, amount) values ('Name', 'Currency', 100);";
stmt.executeUpdate(query);
// execute the preparedstatement
// executing SELECT query
rs = stmt.executeQuery(query);
con.close();
stmt.close();
rs.close();
} catch (SQLException sqlEx) {
sqlEx.printStackTrace();
}
}
}
}
What did I wrong, that nothing happens? Even if I use this code for Java-Classes (not Servlets), I only receive an compile error, but without message.
I'm using the IDE Netbeans and mysql DB is the MySQL Workbench. The Java Class is using the main method.
Update:
I've tested following Code with IntelliJ:
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/userdata";
String user = "root";
String password = "root";
String query = "Insert into customers (customer, currency, amount) values('Michael Ballack', 'Euro', 500)";
try (Connection con = DriverManager.getConnection(url, user, password);
PreparedStatement pst = con.prepareStatement(query)) {
pst.executeUpdate();
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(JdbcMySQLVersion.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
}
}
private static class JdbcMySQLVersion {
public JdbcMySQLVersion() {
}
}
I can insert data into the MySQL database.
In Netbeans this code won't work, although I've implemented the MySQLConnector. I don't know why, but Netbeans seems hard to handle.
In the servlet code, I don't see you ever write anything to out. So nothing is being sent back to the browser, even if it compiled. You could write your SQL exception to the out writer you created. To be more precise add this in your exception: out.println(sqlEx.printStackTrace()); That should at least show what exception you are getting back to the browser.
What is the compile error you get outside of a servlet?
This maybe obvious, but to get JDBC stuff to work on your server, you need to have the MySQL server installed, started and configured. The table referenced has to be defined, etc. You could check this outside of the Java servlet environment with the tools provided with MySQL.
your code can not compile, you miss catch exception for second 'try'.
Where do you use this class to run, if you run a java class, this class must contain main() function?
you should use some IDEs like eclipse or IntelliJ to code, it help you detect the error easier.
I found the solution. If you are using Netbeans with the Glassfish-Server and you want your servlet to save data into the database, you have to make sure that Netbeans has installed the Driver of your Database Connector (e.g. MySQL Connector). But you also have to configurate your server (e.g. Glassfish) which will support the DB Connector drivers.
In my case my Server didn't load the DB Connector Driver so the JDBC Code couldn't be executed.
Here's a useful link to configurate the Glassfish Server: https://dzone.com/articles/nb-class-glassfish-mysql-jdbc

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");

Android-MysqlConnectivity in eclipse

I am new to android, So i need a basic knowledge,How to connect to the database and Select some of the values from it.
These are all the following steps i have already completed by watching and reading some online tutorials.
Created a New ANDROID Project Named And2.
Created a New JAVA Project named MYSQLConnection which is used to store the database connection.
I have Downloaded mysql-connector-java-5.1.34 file Online and added it.
I have attached the Screen Shot the total overview of my eclipse.
Now i just needed to access the database in And2 and Write a Simple Select Query So that i can make sure that connection is created.
Shown below is the Java file for DB Connection.
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import com.mysql.jdbc.*;
//import com.mysql.jdbc.Connection;
//import com.mysql.jdbc.Statement;
public class Main {
public static void main(String[] args) throws Exception
{
Class.forName("com.mysql.jdbc.Driver");
try
{
String connectionUrl = "jdbc:mysql://localhost:3306/testdatabase";
String connectionUser = "root";
String connectionPassword = "12345";
Connection conn = DriverManager.getConnection(connectionUrl, connectionUser,
connectionPassword);
//Statement stmt = conn.createStatement();
// ResultSet reset = stmt.executeQuery("select * from TableName");
//
// //Print the data to the console
// while(reset.next()){
// Log.w("Data:",reset.getString(3));
//
// }
}
catch ( SQLException err )
{
System.out.println("Database connection failed");
}
}
}
Any Help appreciated.

make a connection from my program to database

I am new to programming and i am trying to make a connection from my program to database but when i make the code,error occurred on line 34 (package con.msql.jdbc does not exit).Can u tell me why??help me
code :
package Absensi_PEgawai;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.swing.JOptionPane;
public class koneksi {
private static Connection koneksi;
public static Connection getKoneksi()
{
//cek koneksi
if(koneksi == null)
{
try
{
String url;
url = "jdbc:mysql://localhost:3306/dbabsensipegawai";
String user = "root";
String password = "pk12basketboy";
line34 --> **DriverManager.registerDriver(new con.mysql.jdbc.Driver());**
koneksi = DriverManager.getConnection(url,user,password);
}catch(SQLException t)
{
JOptionPane.showMessageDialog(null, "Error Membuat Koneksi");
}
}
return koneksi;
}
static Object getConnection()
{
throw new UnsupportedOperationException("Not Yet Implemented");
}
}
You must have forgotten to add the database driver to the CLASSPATH. If you are under Eclipse, go to the Build path menu and add your driver, otherwise refer to the billion posts on the internet that explain how to add a class to the CLASSPATH for any system.

Categories