Why connection still commits automatically after putting setAutoCommit(false)? - java

I'm using a MySQL database.
I have a code like this :
public class Test {
public static void main(String[] args) throws SQLException {
String url = "....";
String username = "...";
String password = "...";
DriverManager.registerDriver(new Driver());
Connection connection = DriverManager.getConnection(url, username, password);
connection.setAutoCommit(false);
Statement stmt = connection.createStatement();
stmt.execute("create table if not exists customer1\r\n" + "(\r\n"
+ "customer_name varchar(20) not null primary key,\r\n" + "customer_street varchar(20),\r\n"
+ "customer_city varchar(10)\r\n" + ")");
// connection.commit();
connection.close();
}
}
Problem: When I execute this, it creates the table and commits it automatically but it should not.
I did connection.setAutoCommit(false) and commented out connection.commit() for testing, then why it is committing ?
This question (jdbc autocommit(false) doesnt work) didn't help.

Problem: When I execute this, it creates the table and commits it
automatically but it should not.
Right, any DDL will always be committed regardless of autocommit setting.
This behavior is not specific to MySQL, see Autocommit.
Most DBMS (e.g. MariaDB) force autocommit for every DDL statement,
even in non-autocommit mode. In this case, before each DDL statement,
previous DML statements in transaction are autocommitted. Each DDL
statement is executed in its own new autocommit transaction.
Maybe TEMPORARY TABLE might help you.
You can use the TEMPORARY keyword when creating a table. A TEMPORARY
table is visible only within the current session, and is dropped
automatically when the session is closed. This means that two
different sessions can use the same temporary table name without
conflicting with each other or with an existing non-TEMPORARY table of
the same name. (The existing table is hidden until the temporary table
is dropped.)

MySQL DDL, i.e. creating table isn't transactional
ref transactions that cause implicit commit

Data Manipulation statements are transactional, not Data definition statements.
so create/alter table or drop table are still committed.

Related

JDBC : Batch insert not inserting value to database

I have to execute multiple insert queries using JDBC for which I am trying to execute batch statement. Everything works fine in my code but when i try to see values in the table, the table is empty.
Here is the code :
SessionImpl sessionImpl = (SessionImpl) getSessionFactory().openSession();
Connection conn = (Connection) sessionImpl.connection();
Statement statement = (Statement) conn.createStatement();
for (String query : queries) {
statement.addBatch(query);
}
statement.executeBatch();
statement.close();
conn.close();
And the
List<String> queries
contains insert queries like:
insert into demo values (null,'Sharmzad','10006','http://demo.com','3 Results','some values','$44.00','10006P2','No Ratings','No Reviews','Egypt','Duration: 8 hours','tour','Day Cruises');
And the table structure is like:
create table demo ( ID INTEGER PRIMARY KEY AUTO_INCREMENT,supplierName varchar(200),supplierId varchar(200),supplierUrl varchar(200),totalActivities varchar(200),activityName varchar(200),activityPrice varchar(200),tourCode varchar(200),starRating varchar(200),totalReviews varchar(200),geography varchar(200),duration varchar(200),category varchar(200),subCategory varchar(200));
No exception is thrown anywhere but no value is inserted. Can someone explain?
Most JDBC drivers use autocommit, but some of them do not. If you don't know, you should use either .setAutoCommit(true) before the transaction or .commit() after it..
Could be a transaction issue. Perhaps you're not committing your transaction? If so, then it is normal not to see anything in the database.
You can check if this is the case by running a client in READ_UNCOMMITTED transaction mode, right after .executeBatch(); (but before close()) and see if there are any rows.
You don't should assign a value to ID add supply all the others columns name
insert into demo
(
supplierName
,supplierId
,supplierUrl
,totalActivities
,activityName
,activityPrice
,tourCode
,starRating
,totalReviews
,geography
,duration
,category
,subCategory
)
values (
'Sharmzad'
,'10006'
,'http://demo.com'
,'3 Results'
,'some values'
,'$44.00'
,'10006P2'
,'No Ratings'
,'No Reviews'
,'Egypt'
,'Duration: 8 hours
','tour'
,'Day Cruises'
);
and add commit to your code

neo4j insert using jdbc but cannot query immediately within the same connection

question background:
1.database is neo4j 2.3.1, driver using jdbc;
2.db connection initialized as a class member, default is auto-commit(not changed);
To avoid insert duplicates, i query before insert. after program stopped, found duplicates. why?
code:
String query = "CREATE (n:LABEL {name:'jack'})";
System.out.println(query);
Statement stmt = dbConnection.createStatement();
stmt.executeUpdate(query);
stmt.close();
Use MERGE + unique constraints instead
How do you "check"
You would have to check in the same tx and also take a write lock
after debugging i found that for neo4j-jdbc(v2.1.4), the default db connection transaction level is TRANSACTION_NONE, then i set it to TRANSACTION_READ_COMMITTED, above issue disappeared. so i think that TRANSACTION_READ_COMMITTED will force the previous insert committed, though this is not the recommended way. for isolation level refer to:Difference between read commit and repeatable read

Creating a "Java DB" database and associated tables in main checking to see if they exist?

I'm creating an applicaation on Netbeans 7! I'd like my application to have a little code in main so that it can create a Java DB connection checking to see if the database and the associate tables exist, if not create the database and the tables in it. If you could provide a sample code, it'd be just as great! I have already looked at http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javadb/ but I'm still not sure how to check for an existing database before creating it!
I'd like my application to have a little code in main so that it can create a Java DB connection checking to see if the database and the associate tables exist, if not create the database and the tables in it.
You can add the create=true property, in the JDBC URL. This creates a Derby database instance if the database specified by the databaseName does not exist at the time of connection. A warning is issued if the database already exists, but as far as I know, no SQLException will be thrown.
As far as creation of the tables is concerned, this is best done on application startup before you access the database for typical transactional activity. You will need to query the SYSTABLES system table in Derby/JavaDB to ascertain whether your tables exist.
Connection conn;
try
{
String[] tableNames = {"tableA", "tableB"};
String[] createTableStmts = ... // read the CREATE TABLE SQL statements from a file into this String array. First statement is for the tableA, and so on.
conn = DriverManager.getConnection("jdbc:derby:sampleDB;create=true");
for(int ctr =0 ; ctr < tableNames.length; ctr++)
{
PreparedStatement pStmt = conn.prepareStatement("SELECT t.tablename FROM sys.systables t WHERE t.tablename = ?");
pStmt.setString(1, tableNames[ctr]);
ResultSet rs = pStmt.executeQuery();
if(!rs.next())
{
// Create the table
Statement stmt = conn.createStatement();
stmt.executeUpdate(createTableStmts[ctr]);
stmt.close();
}
rs.close();
pStmt.close();
}
}
catch (SQLException e)
{
throw new RuntimeException("Problem starting the app...", e);
}
Any non-existent tables may then be created. This is of course, not a good practice, if your application has multiple versions, and the schema varies from one version of the application to another. If you must handle such a scenario, you should store the version of the application in a distinct table (that will usually not change across versions), and then apply database delta scripts specific to the newer version, to migrate your database from the older version. Using database change management tools like DbDeploy or LiquiBase is recommended. Under the hood, the tools perform the same operation by storing the version number of the application in a table, and execute delta scripts having versions greater than the one in the database.
On a final note, there is no significant difference between JavaDB and Apache Derby.
I don't know how much Oracle changed Derby before rebranding it, but if they didn't change too much then you might be helped by Delete all tables in Derby DB. The answers to that question list several ways to check what tables exist within a database.
You will specify the database when you create your DB connection; otherwise the connection will not be created successfully. (The exact syntax of this is up to how you are connecting to your db, but the logic of it is the same as in shree's answer.)
The create=true property will create a new database if it is not exists. You may use DatabaseMetadata.getTables() method to check the existence of Tables.
Connection cn=DriverManager.getConnection("jdbc:derby://localhost:1527/testdb3;create=true", "testdb3", "testdb3");
ResultSet mrs=cn.getMetaData().getTables(null, null, null, new String[]{"TABLE"});
while(mrs.next())
{
if(!"EMP".equals(mrs.getString("TABLE_NAME")))
{
Statement st=cn.createStatement();
st.executeUpdate("create table emp (eno int primary key, ename varchar(30))");
st.close();;
}
}
mrs.close();
cn.close();
Connection conn = getMySqlConnection();
System.out.println("Got Connection.");
Statement st = conn.createStatement();
String tableName = ur table name ;
String query = ur query;
Statement stmt = null;
ResultSet rs = null;
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
System.out.println("Exist");;
}
catch (Exception e ) {
// table does not exist or some other problem
//e.printStackTrace();
System.out.println("Not Exist");
}
st.close();
conn.close();

Create database with JPA?

When I create (using JPA - java persistence api) a persistence unit and then persistence entities they auto create the corresponding tables and fields in the database.
Can I also make it to auto create the database (if it doesn't exist)?
My objectif is :
I mean it creates inside the database the tables and fields, but not the database, and if the database hasn't been created before (by hand) - everything fails. So before running the project (which will auto generate the tables and fields if needed) I first must create (by hand) a database.
I use : Eclipse (Java, Hibernate, Flex/Air), MySQL
Thanks for all information
The database has to be created manually (Fortunatly you didn't ask why ;-). Which is similar to the user/password combination you use to connect to your database server, which must already exist in order to connect to the DB.
My solution to this problem was to add the following right before I create my entity manager:
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost/?user=" + DB_USER);
Statement stmt = connection.createStatement();
stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS " + DB_NAME);
You'll need to either surround that with a try/catch block or add a throws SQLException notation to the function in which it exists. So, for example, here is my initEntityManager function:
public static void initEntityManager() throws SQLException {
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost/?user=" + DB_USER);
Statement stmt = connection.createStatement();
stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS " + DB_NAME);
emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
em = emf.createEntityManager();
}

Mysql read data immediately after writing?

I am using a MySQL DB and a Java JDBC client to access it.
I have a Table that contains session information. Each session is associated with a SessionToken. This token is a Base64 encoded String of a Hash of some of the session values. It should be unique. And is defined as varchar(50) in the db.
When I try to lookup a session by its token I query the database using an sql statement like this:
select SessionId, ClientIP, PersonId, LastAccessTime, SessionCreateTime from InkaSession where SessionToken like 'exK/Xw0imW/qOtN39uw5bddeeMg='
I have a UnitTest that tests this functionality, and it consistently fails, because the query does not return any Session, even tough, I have just written the session to the DB.
My Unit test does the following:
Create Connection via DriverManager.getConnection
Add a session via Sql Insert query
close the connection
create Connection via DriverManager.getConnection
look for the session via sql select
unit test fails, because nothing found
When I step through this UnitTest with the debugger and copy past the select sql that is about to be sent to the db into a mysql command line, it works fine, and I get the session row back.
I also tried to retrive an older session from the db by asking for an older SessionToken. This works fine as well. It only fails, if I ask for the SessionToken immediately after I inserted it.
All connections are on AutoCommit. Nevertheless I tried to set the Transaction Level to "Read Uncommited". This did not work either.
Has anyone any further suggestions?
This is typically caused by the connection not being committed between insert and select.
Did you basically do the following?
statement.executeUpdate("INSERT INTO session (...) VALUES (...)");
connection.commit();
resultSet = statement.executeQuery("SELECT ... FROM session WHERE ...");
Edit I tried the following SSCCE on MySQL 5.1.30 with Connector/J 5.1.7:
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = DriverManager.getConnection("jdbc:mysql://localhost/javabase", "root", null);
statement = connection.createStatement();
statement.executeUpdate("INSERT INTO foo (foo) VALUES ('foo')");
resultSet = statement.executeQuery("SELECT id FROM foo WHERE foo = 'foo'");
if (resultSet.next()) {
System.out.println(resultSet.getLong("id"));
} else {
System.out.println("Not inserted?");
}
} finally {
SQLUtil.close(connection, statement, resultSet);
}
}
Works flawlessly. Maybe an issue with your JDBC driver. Try upgrading.
Solved: The two token strings where not identical. One of them had a couple of Zero bytes at the end. (Due to the encrypting and decrypting and padding...) The two strings where visually identical, but MySQL and Java both said, they where not. (And they where right as usual)

Categories