Java Tutorial says there are 2 ways to connect to database thru JDBC: with DriverManager class (old, not recommended) and with DataSource class.
I undestand how to do it with DriverManager:
Connection con = DriverManager.getConnection("jdbc:sqlite:mytest.db");
...
But I cannot find how to use DataSource for SQLite thru JDBC. Does SQLite (or JDBC driver providers for it, I don't know how to call it correctly) support using DataSource at all?
I am using xerial/sqlite-jdbc driver to use SQLite from java (https://github.com/xerial/sqlite-jdbc)
My best guess is that I shall use org.sqlite.SQLiteDataSource class (it comes in sqlite-jdbc-3.15.1.jar for Xerial sqlite-jdbc driver), but how? And is it so? I also guess, that how to do it shall be in Xerial driver docs, but they give only example of how to connect using DriverManager.
So I am asking kind help of guru to confirm that this Xerial driver/jar doesn't support DataSource syntax, or to give example how to do it, or to suggest alternative driver with DataSource support (for SQLite from Java), or advice otherwise...
Java Tutorial
JDBC Driver Manager — The JDBC DriverManager class defines objects
which can connect Java applications to a JDBC driver. DriverManager
has traditionally been the backbone of the JDBC architecture. It is
quite small and simple.
The Standard Extension packages javax.naming and javax.sql let you use
a DataSource object registered with a Java Naming and Directory
Interface™ (JNDI) naming service to establish a connection with a data
source. You can use either connecting mechanism, but using a
DataSource object is recommended whenever possible.
My best guess is that I shall use org.sqlite.SQLiteDataSource class (it comes in sqlite-jdbc-3.15.1.jar for Xerial sqlite-jdbc driver),
Yes, that seems likely.
but how?
I just tried the following and it worked for me:
package com.example.sqlite.sqlite_test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.sqlite.SQLiteDataSource;
public class SqliteTestMain {
public static void main(String[] args) {
SQLiteDataSource ds = new SQLiteDataSource();
ds.setUrl("jdbc:sqlite::memory:");
try (Connection conn = ds.getConnection()) {
System.out.println("Connected.");
String sql =
"SELECT COUNT(*) AS n FROM \"sqlite_master\"";
try (
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(sql)) {
rs.next();
System.out.printf(
"The \"sqlite_master\" table contains %d row(s).%n",
rs.getInt(1));
}
} catch (SQLException e) {
e.printStackTrace(System.err);
}
}
}
Related
I'm developing a Java PLSQL procedure that must instanciate a CLOB object. In order to instanciate that Clob object I must use a connection object. Based on Oracle documentation, I can get the current connection using java.sql.DriverManager however when I execute the following code an AbstractMethodError error is thrown
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
Clob clob = conn.createClob();
I see a lot of posts talking about driver compatibility with Java runtime running the code but as I am working inside an Oracle DB I suppose it should be compatible.
Oracle version: 11.2.0.4.0
My goal is to create a clob inside my java method and return it to my plsql code. How can I instanciate a Clob inside a java class stored inside an Oracle database ?
Thanks for any help !
The creation of the CLOBusing conn.createClob() works for my fine in 12c. I suspect from your error message in 11 you'll have to use the CLOB.createTemporary method to create the CLOB (which works fine in 12c as well but is marked as deprecated).
Here an example
Java class
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "CreateCLOB"
AS
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.*;
/****** START PASTE JAVA CLASS HERE *****/
public class CreateCLOB{
public static void ClobProc (Clob cl[]) throws SQLException
{
Connection conn = DriverManager.getConnection ("jdbc:default:connection:"); /* or use "jdbc:oracle:kprb:" */
Clob clob = CLOB.createTemporary(conn, false, oracle.sql.CLOB.DURATION_SESSION); /* this is deprecated in 12c */
// conn.createClob(); /* works fine in 12.1.0.2.0 */
clob.setString(1, "Test Data");
cl[0] = clob;
}
}
/
Wrapper
create or replace procedure MyClob (cl OUT Clob)
as language java
name 'CreateCLOB.ClobProc(java.sql.Clob[])';
/
Test
declare
x Clob;
begin
MyClob(x);
dbms_output.put_line('created CLOB length = ' || dbms_lob.getlength(x));
end;
/
created CLOB length = 9
As mentioned I can't test it on version 11, but I suppose it will work.
select * from v$version;
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
You need to follow these steps:
1. On your computer you should have an Oracle jdbc driver (http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html)
2. Load a driver
Class.forName("oracle.jdbc.driver.OracleDriver");
3. Get a connection
Connection connection =
DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:SID","username","password");
UPDATE: If you work inside of Oracle DB, you can choose a type of driver (Server-Side Thin Driver or Server-Side Internal Driver) - https://docs.oracle.com/cd/E11882_01/appdev.112/e13995/oracle/jdbc/OracleDriver.html
Even when you are not using the createClob() you may get this error when starting the application if you are using an older version of hibernate core library.
The errors is just thrown, but the application starts. If you are not worried about it you may leave it, but if you don't want to see an error during application startup then her is the fix.
Its a bug in the Spring boot 2.X - hibernate core 5.3.X combination. There are 2 solutions for the issue. I would suggest #1.
Upgrade all hibernate libraries to 5.4.X (my way)
Provide spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true in your application properties/ yml file.(If you really do not want to upgrade your hibernate core library).
I have got this when upgrading spring boot to 2.4 and using Teradata DB without any createClob().
If you still want to know how the error is being created, its well explained in https://alexpask.com/spring-boot-createclob-error/
I recently implemented C3P0 in my database testing program (i'm using it to test different queries on our data in different DB formats... sqlite, mariadb, etc). The program was initially set up using a single sustained connection to do all queries. This worked fine with SQLite as I had to do an initial ATTACH on another table. When moving to C3P0 where it is necessary to open and close the connection on every query, how can one issue an ATTACH command and have it apply to subsequent queries? In my failure I did notice that the first query after the attach it seemed to apply.
Do I really need to interlace ATTACH test as TESTDB for EVERY query???
Running into a similar issue with setCatalog() for MariaDB. I get a "No Database selected" for every subsequent query after the first.
Do I really need to interlace ATTACH test as TESTDB for EVERY query???
No. As #MarkRotteveel suggested in a comment to the question, we can use a c3p0 connection customizer to tweak each connection as it is acquired for the pool. For example, if we create the class OurSQLiteConnectionCustomizer ...
package com.example.sqlite_pooled;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import com.mchange.v2.c3p0.AbstractConnectionCustomizer;
public class OurSQLiteConnectionCustomizer extends AbstractConnectionCustomizer {
public void onAcquire(Connection c, String pdsIdt) throws SQLException {
try (Statement st = c.createStatement()) {
st.execute("ATTACH DATABASE 'C:/__tmp/SQLite/test.sqlite' AS test");
}
}
}
... and we tell our ComboPooledDataSource to use it ...
cpds = new ComboPooledDataSource();
cpds.setConnectionCustomizerClassName("com.example.sqlite_pooled.OurSQLiteConnectionCustomizer");
... then whenever c3p0 acquires a new SQLite connection for the pool it will automatically perform the ATTACH DATABASE for us.
I have added multiple jars(ojdbc6 for oracle and jtds-1.2.jar for sqlserver ) to my classpath.
When I test connection using following code :
Class.forName(JDBC_DRIVER);
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
if(conn==null){
System.out.println("false");
}
else{
System.out.println("true");
}
Scenario 1:
If I give JDBC_DRIVER as sqlserver URL (net.sourceforge.jtds.jdbc.Driver)
and DB_URL,USER,PASS for my oracle instance then also it will create connection for me but logically it is wrong.
Scenario 2:
If I give some other(not oracle.jdbc.driver.OracleDriver ) valid class in ojdbc6.jar and valid DB_URL,USER,PASS then also it will create connection .
But I always want to check valid JDBC_DRIVER which corresponds to the given DB_URL,USER,PASS
I have also tried registerDriver and deregisterDriver API available in driverManager. What are the pros and cons of using it.
Explanation for - Scenario 1/Scenario 2
From oracle documentation
Applications no longer need to explictly load JDBC drivers using Class.forName(). Existing programs which currently load JDBC drivers using Class.forName() will continue to work without modification.
So even you comment out Class.forName(JDBC_DRIVER); you will get the same result as ojdbc6 is in your classpath and in DriverManager.getConnection(...); method you are passing oracle database related information.So DriverManager always will return the connection instance for oracle daabase only.
Explanation for- want to check valid JDBC_DRIVER which corresponds to the given DB_URL,USER,PASS
For this you can use getDriver(String url) method of DriverManager class.
getDriver(String url)
Attempts to locate a driver that understands the given URL.
To check valid driver name try these lines below.
conn = DriverManager.getConnection(this.dbUrl, this.dbUser, this.dbPassword);
DatabaseMetaData dbMetaData = conn.getMetaData();
this.databaseProperties.add("Driver Name: " + dbMetaData.getDriverName());
I have a Jbutton (GetDataFromDB) in a simple java application that is suppose to load the data from the database depicted in the path in the code below into a Jtable in the application.
Edited answer into code:
private void GetDataFromDBActionPerformed(java.awt.event.ActionEvent evt) {
Connection con;
ResultSet rs = null;
Statement stmt;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection("jdbc:odbc:Driver={MS Access Driver (*.mdb, *.accdb)};Dbq=C:\\Users\\Bruger\\Documents\\Database11.accdb");
stmt = con.createStatement();
String query = null;
query = "select * from cost";
rs = stmt.executeQuery(query);
i = 0;
while (rs.next()){
i = i + 1;
jTable.getModel().setValueAt(rs.getString(1), i, 1);
jTable.getModel().setValueAt(rs.getString(2), i, 2);
}
rs.close();
stmt.close();
con.close();
} catch(Exception err){
System.out.println(err.getMessage());
}
}
When I press the button I get the following message in the run output window:
No suitable driver found for jdbc:odbc:Driver={Microsoft Access Driver (.mdb, .accdb)};Dbq=C:\Users\Bruger\Documents\Database11.accdb
I have at the top of my code the import:
import java.sql.*;
I have also tried changing from "Microsoft Access Driver" to "MS Access Driver" but I get the same message in the run output window i.e.
No suitable driver found for jdbc:odbc:Driver={MS Access Driver (.mdb, .accdb)};Dbq=C:\Users\Bruger\Documents\Database11.accdb
I'm really thankful for all your help, input and feedback.
Depending on the driver and If you are pre JDK 6**!
You need to register the driver.
Try adding:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
So:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=C:\\Users\\Bruger\\Documents\\Database11.accdb");
It's also worth mentioning you don't need to do this every time you get a connection, just once to make sure the class is loaded.
There are a lot of stackoverflow questions relating to this, but the reason for it is below:
Source - From The Java Tutorial:
In previous versions of JDBC, to obtain a connection, you first had to
initialize your JDBC driver by calling the method Class.forName. This
methods required an object of type java.sql.Driver. Each JDBC driver
contains one or more classes that implements the interface
java.sql.Driver. ... Any JDBC 4.0 drivers that are found in your class
path are automatically loaded. (However, you must manually load any
drivers prior to JDBC 4.0 with the method Class.forName.)
On a related and very important note.
I would also recommend looking up how to handle connections. External Resources like database connections and cursors are easy to leak if you are not familiar with them. Look up 'try finally blocks', or more recently in java 7+ 'try-with-resources'.
I need to connect to a remote database using Database link using JDBC commands.
How can it be done?
If you already have the dblink setup, you can utilize it in your SQL (sent via jdbc) by addressing the required tables like such:
select * from SCHEMA.TABLE#DBLINK_NAME
Using this query inside of your java would look something like this
public ResultSet execQuery() throws SQLException, ClassNotFoundException{
//Load the database driver
Class.forName("oracle.jdbc.OracleDriver");
//Create connection to the database
Connection myConnection = DriverManager.getConnection(connectURL,userName,userPwd);
//Create a statement link to the database for running queries
Statement myQuery = myConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
//Create a resultSet to hold the returned query information
ResultSet myQueryResults = myQuery.executeQuery("select * from SCHEMA.TABLE#DBLINK_NAME");
return myQueryResults;
}
*java & oracle assumed
If you are asking about how to use JDBC to create a link between the DB you are talking to and another one, then it is "just SQL" that you (presumably) would execute in the same way as you would any other SQL statement. (If you tell us which DB you are using, we could talk about the actual SQL you need to execute.)
Otherwise, I don't think this makes sense. A DB link / Database link is a link from one database to another. But JDBC is for talking to a database from a Java client. It makes no sense (to me) to use DB link to connect a JDBC client to a database.
Please take a look at orajdbclink, on sourceforge
I am planning to to connect my oracle plsql sources to phoenix skin of hbase. It seems to me the unique way to create a connector between oracle and hbase for the moment...