I have created a database file "accounts.accdb" and I'm using the UCanAccess JDBC driver in Eclipse to access it. I can access it fine and update it using my server application but when I close my server application the contents of the database file return to their initial values. My code is below, I have tried using commit() but it doesn't seem to make any difference.
Connection conn=DriverManager.getConnection("jdbc:ucanaccess://accounts.accdb");
//STEP 4: Set auto commit as false.
conn.setAutoCommit(false);
//STEP 5: Execute a query to create statment with
// required arguments for RS example.
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
// Step 6: Execute a SQL SELECT Update.
String sql = "update bankAccounts set " + field + "= " + newValue + " where id = " + id;
System.out.println("update command: " + sql);
stmt.executeUpdate(sql);
System.out.println("Database is updated!!!!");
//STEP 7: Commit data here.
conn.commit();
//STEP 8: Clean-up environment
stmt.close();
conn.close();
Related
I'm using Spring boot 2 with jdbcTemplate in my application. I used Informix.
I'm testing concurrency and I want my application to wait for a while when
a query try to update a row that is locked. This time can be set in informix
with 'SET LOCK MODE TO WAIT 20'. But I'm looking for a method in spring jdbcTemplate or something in spring.
I tried setting a timeout in the jdbcTemplate.setQueryTimeout(60); , but it did not work.
Any idea is welcome.
jdbcTemplate.setQueryTimeout(60);
cachedExecutor.execute(() -> jdbcTemplate.update(updatenIndoPeriodeInLfa()) );
cachedExecutor.execute(() -> jdbcTemplate.update(updatenAfroPeriodeInLfa()) );
private String updatenIndoPeriodeInLfa(){
String query = "UPDATE lfa " +
"set indomonth = 09, indoyear = 2019 , indotype = indo " +
"WHERE lfa.id in (select id " +
" from procindo " +
" where month = 09 and" +
" year = 2019 and" +
" type= indo );";
return query;
}
private String updatenAfroPeriodeInLfa(){
String query = "UPDATE lfa " +
"set afromonth = 09, afroyear = 2019 , afrotype = indo " +
"WHERE lfa.id in (select id " +
" from procafro " +
" where month = 09 and" +
" year = 2019 and" +
" type= afro );";
return query;
}
After digging the Informix documentation I come across this:
Application can use this property to override the default server process for accessing a locked row or table. Gets the value of the IFX_LOCK_MODE_WAIT variable, which is specific to Informix. The default value is 0 (do not wait for the lock). If the value has been set explicitly, it returns the set value. Returns: integer.
Sets the value of the IFX_LOCK_MODE_WAIT variable, which is specific to Informix.
Possible values:
-1
WAIT until the lock is released.
0
DO NOT WAIT, end the operation, and return with error.
nn
WAIT for nn seconds for the lock to be released.
Then in my application datasource configuration, passed this property in as below:
#Bean(name = "informixDataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.informix.jdbc.IfxDriver");
Properties properties = new Properties();
properties.put("IFX_LOCK_MODE_WAIT", "60");
dataSource.setConnectionProperties(properties);
dataSource.setUrl(jdbc.getUrl());
dataSource.setUsername(jdbc.getUser());
dataSource.setPassword(jdbc.getPassword());
return dataSource;
}
I have made a java script that will connect to hive using Hiveserver2 and will create table and manage tables, for simple create, drop, insert data works fine.
I want to create external table with partition, for this I need to change the value for the following hive property,
hive.exec.dynamic.partition = true
hive.exec.dynamic.partition.mode = nonstrict
In hive cli I can do it using SET and the property name, but how can this be done in java code.
Here is my Java code:
public class HiveJdbcClient {
private static String strDriverName = "org.apache.hive.jdbc.HiveDriver";
public static void main(String[] args) throws SQLException {
try{
Class.forName(strDriverName);
} catch (ClassNotFoundException e){
e.printStackTrace();
System.out.println("No class found");
System.exit(1);
}
Connection con = DriverManager.getConnection("jdbc:hive2://172.11.1.11:10000/default","root","root123");
Statement stmt = con.createStatement();
String strTableName = "testtable";
//stmt.execute("drop table " + strTableName);
//creating staging table that will load the data to partition data
String strStagingTableSql = "create table if not exists "+strTableName+"_staging "+ " (SEQUENCE_NO DECIMAL, DATE_KEY INT, ACTIVITY_TIME_KEY INT, Ds_KEY INT, Ds_VALUE DECIMAL, TL_DATE_KEY INT) ROW FORMAT DELIMITED FIELDS TERIMANTED BY '~'";
String strMainTableSql = "create external table if not exists "+strTableName+" (SEQUENCE_NO DECIMAL, ACTIVITY_TIME_KEY INT, Ds_KEY INT, Ds_VALUE DECIMAL, TL_DATE_KEY INT) PARTITIONED BY (DATE_KEY INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '~' LOCATION '/informatica/dwh/teradata/testtable'";
String strCreateSql = "create external table if not exists "+ strTableName + " (key int, value string) row format delimited fields terminated by ','";
boolean res = stmt.execute(strCreateSql);
//show tables
String sql = "show tables '" + strTableName + "'";
ResultSet res1 = stmt.executeQuery(sql);
if (res1.next()){
System.out.println(res1.getString(1));
}
sql = "describe "+ strTableName;
System.out.println("Running: "+ sql);
res1 = stmt.executeQuery(sql);
while (res1.next()){
System.out.println(res1.getString(1) + "\t" + res1.getString(2));
}
// load data into table
// NOTE: filepath has to be local to the hive server
// NOTE: /tmp/a.txt is a ctrl-A separated file with two fields per line
String strFilepath = "/informatica/testing_hive_client_java.txt";
sql = "load data inpath '" + strFilepath + "' into table " + strTableName;
System.out.println("Running: " + sql);
res = stmt.execute(sql);
sql = "select count(1) from "+ strTableName;
System.out.println("Running: "+ sql);
res1 = stmt.executeQuery(sql);
while(res1.next()){
System.out.println(res1.getString(1));
}
}// end of main
}// end of class
Experts please pour in your thoughts.
I was able to solve my problem by following code.
boolean resHivePropertyTest = stmt
.execute("SET hive.exec.dynamic.partition = true");
resHivePropertyTest = stmt
.execute("SET hive.exec.dynamic.partition.mode = nonstrict");
As the code is JDBC client code , so the execute will just go and execute this in hive and so that worked for me.
After I replaced mysql jdbc driver 5.1 with mariadb jdbc driver 1.1.5 and tested the existing code base that connected with MySQL Server 5.0 and MariaDB Server 5.2, everything works fine except a JDBC call to update a blob field in a table.
The blob field contains XML configuration file. It can be read out, and convert to xml and insert some values.
Then convert it to ByteArrayInputStream object, and call the method
statement.updateBinaryStream(columnLabel, the ByteArrayInputStream object, its length)
but an exception is thrown:
Perhaps you have some incorrect SQL syntax?
java.sql.SQLFeatureNotSupportedException: Updates are not supported
at
org.mariadb.jdbc.internal.SQLExceptionMapper.getFeatureNotSupportedException(SQLExceptionMapper.java:165)
at
org.mariadb.jdbc.MySQLResultSet.updateBinaryStream(MySQLResultSet.java:1642)
at
org.apache.commons.dbcp.DelegatingResultSet.updateBinaryStream(DelegatingResultSet.java:511)
I tried updateBlob method, the same exception was thrown.
The code works well with mysql jdbc driver 5.1.
Any suggestions on how to work around with this situation?
See the ticket updating blob with updateBinaryStream, which in commnet states that it isn't supported.
A workaround would be to use two SQL statements. One which is used to select the data and other to update the data. Something like this:
final Statement select = connection.createStatement();
try {
final PreparedStatement update = connection.prepareStatement( "UPDATE table SET blobColumn=? WHERE idColumn=?" );
try {
final ResultSet selectSet = select.executeQuery( "SELECT idColumn,blobColumn FROM table" );
try {
final int id = selectSet.getInt( "idColumn" );
final InputStream stream = workWithSTreamAndRetrunANew( selectSet.getBinaryStream( "blobColumn" ) ) );
update.setBinaryStream( 1,stream );
update.setInt( 2,id );
update.execute();
}
finally {
if( selectSet != null )
selectSet.close();
}
}
finally {
if( update != null )
update.close();
}
}
finally {
if( select != null )
select.close();
}
But be aware that you need some information how to uniquely identify a table entry, in this example the column idColumn was used for that purpose. Furthermore is you stored empty stream in the
database you might get an SQLException.
A simpler work around is using binary literals (like X'2a4b54') and concatenation (UPDATE table SET blobcol = blobcol || X'2a4b54') like this:
int iBUFSIZ = 4096;
byte[] buf = new byte[iBUFSIZ];
int iLength = 0;
int iUpdated = 1;
for (int iRead = stream.read(buf, 0, iBUFSIZ);
(iUpdated == 1) && (iRead != -1) && (iLength < iTotalLength);
iRead = stream.read(buf, 0, iBUFSIZ))
{
String sValue = "X'" + toHex(buf,0,iRead) + "'";
if (iLength > 0)
sValue = sBlobColumn + " || " + sValue;
String sSql = "UPDATE "+sTable+" SET "+sBlobColumn+"= "+sValue;
Statement stmt = connection.createStatement();
iUpdated = stmt.executeUpdate(sSql);
stmt.close();
}
I'm using ODP.NET to access Oracle DB from C# .NET.
Please see following code:
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=user;Password=pass;Data Source=localhost/orcl";
con.Open();
/* create table */
DbCommand command = con.CreateCommand();
command.CommandType = CommandType.Text;
try
{
command.CommandText = "DROP TABLE TEST";
command.ExecuteNonQuery();
}
catch
{
}
//command.CommandText = "CREATE TABLE TEST (VALUE BINARY_DOUBLE)";
command.CommandText = "CREATE TABLE TEST (VALUE FLOAT(126))";
command.ExecuteNonQuery();
/* now insert something */
double val = 0.8414709848078965;
command.CommandText = "INSERT INTO TEST VALUES (" + val.ToString(System.Globalization.CultureInfo.InvariantCulture) + ")";
command.ExecuteNonQuery();
/* and now read inserted value */
command.CommandText = "SELECT * FROM TEST";
DbDataReader reader = command.ExecuteReader();
reader.Read();
double res = (double) (decimal)reader[0];
Console.WriteLine("Inserted " + val + " selected " + res);
The output from this is always:
Inserted 0,841470984807897 selected 0,841470984807897
But looking at variable values under debugger
val == 0.8414709848078965
res == 0,841470984807897
Why res is rounded up?
I looked into DB and there is stored rounded-up value.
On the other hand I used Oracle SQL Developer to modify this value, and I'm able to store 0.8414709848078965 in database?
I tried types NUMBER, FLOAT(126), BINARY_DOUBLE... always the same result.
Why there is a problem using ODP.NET?
OK, I have found that it works if parameter type is OracleDbType.BinaryDouble. But it causes my code to be dependent of ODP.NET. I wanted to use ADO.NET types (DbType) to achieve my code independency.
Oracle actually has a higher precision for it's numbers than .net!
I tried this in straight Oracle and it works fine, I recommend changing to use a param
e.g.
-- CREATE TABLE TEST (VALUE NUMBER(38,38)); (initial test)
INSERT INTO TEST VALUES (0.8414709848078965);
SELECT * FROM TEST;
VALUE
----------------------
0.8414709848078965
(recommendation)
OracleParameter param = cmd.CreateParameter();
param.ParameterName = "NUMBERVALUE";
param.Direction = ParameterDirection.Input;
param.OracleDbType = OracleDbType.Decimal;
param.Value = "0.8414709848078965";
command.Parameters.Add(param);
I have the following query (column log is of type CLOB):
UPDATE table SET log=? where id=?
The query above works fine when using the setAsciiStream method to put a value longer than 4000 characters into the log column.
But instead of replacing the value, I want to append it, hence my query looks like this:
UPDATE table SET log=log||?||chr(10) where id=?
The above query DOES NOT work any more and I get the following error:
java.sql.SQLException: ORA-01461: can bind a LONG value only for insert into a LONG column
It looks to me like you have to use a PL/SQL block to do what you want. The following works for me, assuming there's an entry with id 1:
import oracle.jdbc.OracleDriver;
import java.sql.*;
import java.io.ByteArrayInputStream;
public class JDBCTest {
// How much test data to generate.
public static final int SIZE = 8192;
public static void main(String[] args) throws Exception {
// Generate some test data.
byte[] data = new byte[SIZE];
for (int i = 0; i < SIZE; ++i) {
data[i] = (byte) (64 + (i % 32));
}
ByteArrayInputStream stream = new ByteArrayInputStream(data);
DriverManager.registerDriver(new OracleDriver());
Connection c = DriverManager.getConnection(
"jdbc:oracle:thin:#some_database", "user", "password");
String sql =
"DECLARE\n" +
" l_line CLOB;\n" +
"BEGIN\n" +
" l_line := ?;\n" +
" UPDATE table SET log = log || l_line || CHR(10) WHERE id = ?;\n" +
"END;\n";
PreparedStatement stmt = c.prepareStatement(sql);
stmt.setAsciiStream(1, stream, SIZE);
stmt.setInt(2, 1);
stmt.execute();
stmt.close();
c.commit();
c.close();
}
}
BLOBs are not mutable from SQL (well, besides setting them to NULL), so to append, you would have to download the blob first, concatenate locally, and upload the result again.
The usual solution is to write several records to the database with a common key and a sequence which tells the DB how to order the rows.