This question already has answers here:
Why do I get java.lang.AbstractMethodError: oracle.jdbc.driver.OracleConnection error?
(2 answers)
Closed 6 years ago.
So I'm having a big issue with CLOBs and Oracle. Up until now, the database my company has been using for this one client has just been passed simple Strings through a PreparedStatement. This has been fine, because those Strings have all been less than 4,000 characters. We just discovered that limit exists. Not 100% sure why, believe it's something related to how CLOBs behave. Anyway, I have been assigned to go into the code and fix this.
So, at the moment, the PreparedStatement has its parameters assigned through a very simple process:
((PreparedStatement) stmt).setObject(fieldIndex++, fieldInfo.value);
This has worked well enough for now, but obviously not so much going forward.
Anyway, so my first thought was to try and use some of the PreparedStatement methods related to CLOBs. fieldInfo.value is a declared type of Object, with its actual type set dynamically. Up until now, it's been kept as a String, as I said, so I decided I would just change its type and then use one of the PreparedStatement methods to assign it.
I've tried the following value types & PreparedStatement methods:
if(fieldInfo.value instanceof InputStream){
((PreparedStatement) stmt).setBinaryStream(fieldIndex++, (InputStream) fieldInfo.value);
}
if(fieldInfo.value instanceof Reader){
((PreparedStatement) stmt).setCharacterStream(fieldIndex++, (Reader) fieldInfo.value);
}
if(fieldInfo.value instanceof Clob){
((PreparedStatement) stmt).setClob(fieldIndex++, (Clob) fieldInfo.value);
}
I'm obviously not calling all of those in a row, those are just examples of what I've tried separately.
Every one of those has the same result: AbstractMethodError. Upon researching that exception, I saw that the issue is most likely my JDBC driver. Except... as far as I can tell, I'm on the right one. I've tried this with ojdbc6 & ojdbc7, same error. I've scoured my classpath, and every directory in the project, for any indication that an older jar is hiding there, and I can't seem to find one.
Does anyone have any idea what could be happening?
Wow, what a weird issue. There was an old oracle driver buried inside another jar that had been sitting around for years. Ah, the wonders of legacy applications that haven't had a good code rebasing ever.
Anyway, any mods that see this can close this question.
I don't know what a command do you want to execute in your code, is it INSERT, UPDATE or some other command ?
However I simply followed the manual "JDBC Developer's Guide", a topic "Working with LOBs and BFILEs" ==> http://docs.oracle.com/cd/E11882_01/java.112/e16548/oralob.htm#JJDBC28535
and everything worked fine.
They wrote in the documentation that:
In Oracle Database 11g release 2 (11.2), the setBytes,
setBinaryStream, setString, setCharacterStream, and setAsciiStream
methods of PreparedStatement are extended to enhance the ability to
work with BLOB, CLOB, and NCLOB target columns.
They say that setString must work with strings > 4000 char, then I've created this simple test case, I used ojdbc6 driver (for Oracle 11.2), see below:
CREATE TABLE myclob(
id int,
myclob clob
);
================================
public static void main(String ...x) throws SQLException{
OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:thin:#//localhost:1521/orcl");
ods.setUser("test");
ods.setPassword("test");
Connection con = ods.getConnection();
PreparedStatement stmt = con.prepareStatement("INSERT INTO myclob( id, myclob) VALUES (?, ?)");
StringBuffer str = new StringBuffer();
for(int i = 0; i<1000; i++)
str.append("Very long line number = " + i);
System.out.println( "The length is: " + str.length());
stmt.setInt(1, 2);
stmt.setString(2, str.toString());
stmt.executeUpdate();
con.commit();
stmt.close();
con.close();
}
================================
select length( m.myclob), m.*
from myclob m;
LENGTH(M.MYCLOB) ID MYCLOB
---------------- ---------- --------------------------------------------------------------------------------
26890 2 Very long line number = 0Very long line number = 1Very long line number = 2Very
Related
Very much a beginner, this relates to a college project and as such I understand if you are unwilling to solve the problem for me, but I would appreciate being pointed in the right direction if possible.
The below code is a snippet from my database management class for a project.
I'm keeping an ArrayList of users within the java project, loading it if possible from the database at runtime and saving back to the database when closed. Any changes to the users are made in the app (just a JavaFX GUI) and only reflected in the database at shutdown.
For this reason, I need it to be a "INSERT IF NOT EXISTS" type of statement.
I tried this originally without the complex INSERT...SELECT, it just plain inserted the user, causing duplicates. This caused duplicates, but otherwise worked, updating and reading from the database as expected with no errors, even on the ArrayList to byte array to BLOB part, which was very much stretching my Java ability.
I also understand that there are some examples of poor encapsulation in my code, but I am more concerned with the fact that the code runs, no errors, and even in the debugger the prepared statement seems to be getting formed correctly, but the database fails to be updated, with or without duplicates.
Any help, whether a solution, work around or suggestion as to where to go looking for a cause, would be much appreciated.
public static void saveUsers(ArrayList<User> users){
makeConn();
try{
for (User u : carbonapp.CarbonApp.userList.users){
String n = u.getName();
String p = u.getPass();
boolean a = u.getIsAdmin();
UserActivityList l = u.list;
byte[] m = null;
try {
m = toByteArray(l.getUserActivities());
} catch (IOException ex) {
Logger.getLogger(dbStor.class.getName()).log(Level.SEVERE, null, ex);
}
Blob ualblob = new SerialBlob(m);
String sql = "INSERT INTO root.person (name,pass,isAdmin,ual)\n" +
"SELECT CAST(? as VARCHAR(50)),CAST(? as VARCHAR(50)),CAST(? as BOOLEAN),CAST(? as BLOB) " +
"FROM root.person WHERE NOT EXISTS (SELECT name FROM root.person WHERE name = ? AND pass = ?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, n);
pstmt.setString(2, p);
pstmt.setBoolean(3, a);
pstmt.setBlob(4, ualblob);
pstmt.setString(5, n);
pstmt.setString(6, p);
pstmt.executeUpdate();
conn.commit();
}}catch(SQLException se){se.printStackTrace();
}try{conn.close();
}catch(SQLException se){se.printStackTrace();}
}
FYI, I'm using a derby database, working in Netbeans. The makeConn(); function creates the connection and works in other cases, it sets a static Connection conn which is used in the shown code.
Again, no error messages, no crashes or other issues there, just an empty table "person", the desired result being that the table gets updated with the values, in the case that those values don't exists already.
I am trying to retrieve data from DB2 using Java prepared statement
String select_statement = "SELECT * FROM schema_name.table_name where NME='xxx002' and LINE =7200 and FILE_NME='720001042021XYZ002' with ur";
try (Connection connection = DataBaseConnection.getGeoCarDBConnection_TESTDATA();
PreparedStatement ps = connection.prepareStatement(select_statement);) {
ResultSet rs = null;
rs = ps.executeQuery();
}
The problem I am facing is that I include the FILE_NME in the where clause of the query, as shown above, 0 rows are returned. But any other string fields can be passed and I get the desired number of rows.
Any integer fields in the where clause works too.
But only the string fields that are large(In this case, FILE_NME field) are not working. In the DB2 table, where I am pulling the data from, the FILE_NME field is of varchar(30).
Things that did not work for me was
String select_statement = "SELECT * FROM schema_name.table_name where NME='xxx002' and LINE =7200 and FILE_NME = ? with ur";
then I set the String value using,
ps.setString(1, "'720001042021XYZ002'")
ps.setString(1, "720001042021XYZ002")
Both did not work.
None of the google links were helpful. Have spent more than a day on it.
This code used to work flawlessly before, Even the java version hasn't changed(as per my knowledge)
I am running it in windows 10.
Java version : 1.8 ((build 1.8.0_221-b11))
I run the same query in the database client and it works.
Someone please help me or point me in the right direction. I don't know what I am missing
Thank in advance
The problem was that there was indeed no data, I was checking the same query in the database client in a different environment. I am closing this.
I have table called mpi which contains 23 columns. I have introduced the search field with button for every column where user can enter the query to fetch the records using query
query="select * from mpi where Genus ='"+genus+"'
Now I want to fetch records by giving keywords using LIKE %% but it is not working and not giving any records but if type type the full name it is working perfectly. Here is the code
String uname=request.getParameter("uname");
String full="%"+uname+"%";
dbconn=new DatabaseConnection();
conn=dbconn.setConnection();
pstmt=conn.prepareStatement("select * from mpi where Genus LIKE ?");
pstmt.setString(1, full);
res=pstmt.executeQuery
Could any one tell me where is the mistake and why I am not getting the records when I use half keyword like %keyword%.
It works (apart from the missing parentheses) and the approach with a prepared statement is entirely correct.
However I have seen a couple of code pieces like that, and always the problem lay with variables mix-up or not closing, or simple oversight. Better declare as close as possible.
try (ResultSet res = pstmt.executeQuery()) {
while (res.next()) {
..
}
} // Automatically closes res.
Also handle the life-cycle of pstmt correctly, with closing.
iv created a program which works really well with MySQL. However, when I convert it to SQLlite, everything works such as Creating tables, getConnection() to the database and such EXCEPT inserting values to the table??
I am unable to insert value to the table using Java (Netbeans) to SQLite database. I can only insert ONE row but not multiple rows? In MySQL, i could insert multiple rows at once, however, I cant in SQLite?
The code is (This works for only ONE row):
Connection con;
Statement s= con.CreateStatement();
String st = "Insert into table1 (10,'abc')";
s.executeUpdate(st);
s.close();
If I do something like this (DOES NOT work for more than one row - have no idea why- SQLite):
Connection con;
Statement s= con.CreateStatement();
String st = "Insert into table1 (10,'abc'), (5,'vfvdv')"; //now it doesnt work since Im inserting more than one row. I can't figure out what Im doing wrong -
//Iv also tried Insert into table1(ID, Name) values (10,'abc'), (5,'afb'); but it dont work.
s.executeUpdate(st);
s.close();
Could any java expert or anyone help me on this. I cant figure out what Im doing wrong or anything because when I type my commands in the 'SQLite' command line it works fine for ALL. But, In JAVA with SQLite, I can only update one row for some reason?
However, Java with MySQL works fine but not SQLlite.
Anyone could clarify what Im doing wrong would be brillant.
Thanks alot for reading this and your time.
It's possible that the SQLite JDBC driver doesn't support the multi-insert syntax. This syntax is also not standard, though many databases do support it.
Another option for doing multiple inserts like this is to use the batching mechanism of PreparedStatement.
Connection conn = ....;
PreparedStatement stmt =
conn.prepareStatement("INSERT INTO table1(id, name) VALUES (?, ?)");
stmt.setInt(1, 10);
stmt.setString(2, "abc");
stmt.addBatch();
stmt.setInt(1, 5);
stmt.setString(2, "vfvdv");
stmt.addBatch();
stmt.executeBatch();
Typically, you'd use the setInt, setString, addBatch sequence in a loop, instead of unrolled as I've shown here, and call executeBatch after the loop. This will work with all JDBC compliant databases.
Multi row insert is not standard according to the SQL92 standard.
SQLite suports it since version 3.7.11.
If you have a version under this one, you need to make one insert for each row...
I am working a Airsoft application.
I'm trying to add records to a MS Access Database via SQL in Java. I have established a link to the database, with the following:
try
{
//String Driver = "sun.java.odbc.JdbcOdbcDriver";
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://" + URL,"","");
Statement stmt = conn.createStatement();
System.out.println("Connection Established!");
ResultSet rs = stmt.executeQuery("SELECT * FROM AirsoftGunRentals");
tblRent.setModel(DbUtils.resultSetToTableModel(rs));
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error");
}
I am using Ucanaccess to access my MS database. It is reading the database and is displaying to a JTable. However, I need to create three JButtons to add, delete and update the table. I have tried to code the add button, and I have tried to add a record, but it crashes and gives me errors.
try
{
//String Driver = "sun.java.odbc.JdbcOdbcDriver";
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://" + URL,"","");
Statement stmt = conn.createStatement();
System.out.println("Connection Established!");
String Query= "INSERT INTO AirsoftGunRentals(NameOfGun, Brand, TypeOfGuns, NumberOfMagazines,Extras,NumberAvailable,UnitRent)"+
"VALUES('"+pName+"','"+pBrand+"','"+pTypeOfGun+"','"+pNumMags+"','"+pExtras+"','"+pNumberAvail+"','"+pRent+"');";
ResultSet rs = stmt.executeQuery(Query);
JOptionPane.showMessageDialog(null, "Success!");
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error");
}
I have attempted all three, hoping for a result. But am still getting big errors. The only difference between the buttons is that one adds, one deletes and one updates the table. Other then that, the code is the same, minus variables.
As Brahim mentionned it, you should use stmt.executeUpdate(Query) whenever you update / insert or delete data. Also with this particular query, given your String concatenation (see end of line), there is no space between the ")" and the "VALUES" which probably causes a malformed query.
However, I can see from your code that you are not very experienced with such use-cases, and I'd like to add some pointers before all hell breaks loose in your project :
Use PreparedStatement instead of Statement and replace variables by placeholders to prevent SQL Injection.
The code that you are using here is extremely prone to SQL injection - if any user has any control over any of the variables, this could lead to a full database dump (theft), destruction of data (vandalism), or even in machine takeover if other conditions are met.
A good advice is to never use the Statement class, better be safe than sorry :)
Respect Java Conventions (or be coherent).
In your example you define the String Query, while all the other variables start with lower-case (as in Java Conventions), instead of String query. Overtime, such little mistakes (that won't break a build) will lead to bugs due to mistaking variables with classnames etc :)
Good luck on your road to mastering this wonderful language ! :)
First add a space before the quotation marks like this :
String Query= "INSERT INTO AirsoftGunRentals(NameOfGun, Brand, TypeOfGuns, NumberOfMagazines,Extras,NumberAvailable,UnitRent) "+
" VALUES('"+pName+"','"+pBrand+"','"+pTypeOfGun+"','"+pNumMags+"','"+pExtras+"','"+pNumberAvail+"','"+pRent+"');";
And use stmt.executeUpdate(Query); instead of : stmt.executeQuery(Query);in your insert, update and delete queries. For select queries you can keep it.
I managed to find an answer on how to add, delete and update records to a MS Access DB. This is what I found, after I declared the connection, and the prepped statement. I will try to explain to the best I can. I had to add values individually using this:
(pstmt = Prepped Statement Variable)
pstmt.setWhatever(1,Variable);
And it works fine now. I use the same method to delete and update records.
This is the basic query format:
String SQLInsert = "INSERT INTO Tbl VALUES(NULL,?,?,?,?)";
The NULL in the statement is the autonumber in the table. and .setWhatever() clause replaces the question marks with the data types. Thus manipulating the database.
Thank you everyone for all your contributions. It helped a lot, and made this section a lot more understandable.