Searching in sql, Transactions and DB File Locked - java

I am using JavaFX with SQLite DB for making a general store management. Previously I was using SQL server as an assignment but to implement it I needed an embedded database. For that purpose I chose SQLite. Here I faced many problems as it didn't have stored procedures now I got the following 3 problems in my whole management System:
Error in searching through query
Error in executing a transaction
Getting error message that database file is locked.
Now I am going to define each part separately.
1.Error in Searching through query
I was using stored procedure in SQL server for searching in a table using some text the inner query was:
Create PROC [dbo].[spGetProductListByQuery]
#query varchar(MAX)
AS
BEGIN
SELECT p.Product_id, p.Name, pt.Type, p.Pur_Price, p.Sale_Price, p.Stock,s.Name, s.Contact_No, s.Email
FROM ((Product AS p
INNER JOIN ProductType AS pt ON p.Type_Id=pt.Type_Id)
INNER JOIN Supplier AS s ON p.Supplier_Id=s.Supplier_Id)
WHERE p.Name LIKE #query+'%'
And in java i executed this stored procedure using following code:
pst=con.prepareStatement("EXEC spGetProductListByQuery #query=?");
pst.setString(1,query)
and it worked at that time but now as i am using SQLite studio for that purpose i am using following code:
sql="SELECT p.Product_id, p.Name, pt.Type, p.Pur_Price, p.Sale_Price, p.Stock,s.Name, s.PhoneNumber, s.Email\r\n" +
"FROM ((Product AS p\r\n" +
"INNER JOIN ProductType AS pt ON p.Type_Id=pt.Type_Id)\r\n" +
"INNER JOIN Supplier AS s ON p.Supplier_Id=s.Supplier_Id)\r\n" +
"WHERE p.Name LIKE ?+'%'";
System.out.println(searchText);
pst=con.prepareStatement(sql);
pst.setString(1, searchText);
rs=pst.executeQuery();
it works on SQLite studio but it returns nothing java, i can't understand where is the problem.
2.Error in executing a transaction
I have tried for so many time to execute even a single statement in transaction but it still returns error message as shown below:
BEGIN TRANSACTION;
INSERT INTO Staff (Name, Address, Contact_No,Salary,Accountant)
VALUES ('Danish', 'Gujrat','034803','22000,0)
END TRANSACTION
and i got following error message:
cannot start a transaction within a transaction Unable to fetch row.
3. Getting error message that database file is locked
As the 3rd problem is connected to 2nd problem if it resolves I can use multiple statements in one SQL Transaction and make it possible to work. But the strange thing is that when I tried to execute this function:
public static Boolean saleItem(int productId, double quantity) {
con=Connectivity.getConnectivity();
Connection con2 = null;
try {
if(productId!=0&&quantity!=0)
pst=con.prepareStatement("INSERT INTO SALE (Product_Id, Date, Quantity)\r\n" +
"VALUES (?, CURRENT_TIMESTAMP, ?)");
pst.setInt(1, productId);
pst.setDouble(2, quantity);
pst.executeUpdate();
if(!con.isClosed()) {
con.close();
}
pst=con.prepareStatement("UPDATE Product\r\n" +
"SET Stock=Stock-? WHERE Product_id=?");
pst.setInt(2, productId);
pst.setDouble(1, quantity);
pst.executeUpdate();
con.close();
} catch (SQLException e) {
//showErrorAlert(e.getMessage());
e.printStackTrace();
return false;
}catch(NullPointerException e) {
showErrorAlert(e.getMessage());
}
return true;
}
here we can see that two connections are being established at one time and it shows the error message
org.sqlite.SQLiteException: [SQLITE_BUSY] The database file is locked (database is locked)
But when I tried to execute the function having only one connection instances in which update query was executed:
public static void changeStock(double quantity, int id) {
con=Connectivity.getConnectivity();
if(quantity!=0) {
try {
pst=con.prepareStatement("UPDATE Product \r\n" +
"SET Stock=Stock+(?) \r\n" +
"WHERE Product_id=?");
pst.setDouble(1, quantity);
pst.setInt(2, id);
} catch (SQLException e) {
showErrorAlert(e.getMessage());
e.printStackTrace();
}
}
}
it still showed the error that is shown above.
My problems are a little long but hope so that you can help me.
Thanks

Related

Observing Java Null pointer exception issue when we try to fetch the records from Informix db

Issue:
In DB, Have around 20000 records and I'm trying to generate the report of all the records via UI ,it fetches the records available in db till 12679th record . When it tries to generate the records for 12680th one, Observing the below mentioned error in the UI page. As a result, observing java null pointer exception issue.
Note: Handled the code to fetch around 30000 records via preparedStatement object(setMaxRows)
Errors Observed:
Unable to Execute Query:Could not open database table(root.tablename).
select * from tablename a where x=12680 order by y;
Exception in thread "main" java.lang.NullPointerException
And it has been observed due to this piece of code
s1 is the select query which we are parsing as an argument to the prepareStatement.
pStmt is nothing but the preparedStatement object.
dbCon is connection object
Looped through the query for each records one by one
private Connection dbCon;
PreparedStatement pStmt = null;
try {
pStmt = dbCon.prepareStatement (s1);
try {
pStmt.setMaxRows(30000);
rs = pStmt.executeQuery ();
} catch (Exception e) {
System.out.println ("\nUnable to Execute Query:" + e.getMessage() +"Stack Trace::"+e.getStackTrace() + " (Query: " + s1 + ")\n");
}
} catch (Exception e) {
System.out.println ("\nUnable to Prepare Query:" + e.getMessage() + " (Query: " + s1 + ")\n");
}
When we execute the select query command for 12680th record via CLI informix db access, the query seems to be working fine and it fetches the record without any issues.
It looks like a java issue because if its a db issue ,it should not allow us to fetch the query results via CLI but it allows us to fetch without any issues via informix db access.
Got struct at this point on how to solve this java exception issue?
Could someone guide me to proceed further on this activity to fix the issue?
Expectation:
Need to capture all the 20000 records

SQLSyntaxErrorException

I made one table Login using oracle. Firstly I have taken fields- id,username,password and connected database in java program for signup. I was trying to execute insert query before it was running fine than I altered table Login and dropped column id. Then again I tried to run insert query from java program but now I am getting below error. I am not getting what happened after alteration. I think changes should reflect everywhere but I am stuck with this exception.
java.sql.SQLSyntaxErrorException: ORA-04098: trigger 'SURABHI.BI_LOGIN' is invalid and failed re-validation
JAVA CODE:
public void insertLogin(String user,String pass) {
String query = "insert into Login(username,password)" + " values(?,?)";
try {
ps = con.prepareStatement(query);
ps.setString(1, user);
ps.setString(2, pass);
ps.execute();
System.out.println("inserted");
} catch(Exception e) {
e.printStackTrace();
}
}
It seems your table has a before insert trigger and it is invalid, probably because you dropped column id and it is used by the trigger.
Check your trigger and compile it successfully.

SQLite Database locking up on Delete Command

I have a problem where I can't seem to get this simple delete command working. Everytime I run it it just locks the database and crashes
The id parameter exists in the database
the database is small. Only a few tables.
update commands work completely fine.
The id is an in and resulting command is - DELETE from Employees where ID = 2;
public static void EmployeeDeleteByID(int idIn){
Connection c = null;
Statement stmt = null;
try {
c = Connect();
c.setAutoCommit(false);
System.out.println("Opened database successfully");
stmt = c.createStatement();
String sql = "DELETE from Employees where ID = " + idIn + ";";
System.out.println(sql);
stmt.executeUpdate(sql);
c.commit();
stmt.close();
c.close();
} catch ( Exception e ) {
System.err.println("Error 1 : " + e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Operation done successfully");
}
Error after running : java.sql.SQLException: database is locked
"database is locked" means that some other connection still has an active transaction.
If there is no other process accessing the database, you have to check all connections in your program; at least one of them forgot a commit().
The code actually works fine.
It turned out another method was being called to fill a JCombo which was keeping a connection open due to an error being caused by calling a null value from database.
It wasnt obvious as there was no code in the exception box.
Silly little problem so people always make an error throw some kind of stack trace or warning.
Thanks

How to insert and select from mysql simultaneously

I have a requirement where I need to insert mobile number in mysql if and only if the number is is not present.So for this I am first checking if a number is present in mysql using select query .If number is not present then insert.Following is my code
PreparedStatement pt1=con.prepareStatement("select * from registerSmsUsers where mobile='"+mobile+"'");
PreparedStatement pt=con.prepareStatement("insert into registerSmsUsers values(?,?,?)");
pt.setString(1, name);
pt.setString(2, email);
pt.setString(3, mobile);
ResultSet rs1=pt1.executeQuery();
if(rs1.next())
{pt.executeUpdate();}
i dont know whether this is a efficient way or not.Please suggest me a better way then this
Probably the easiest way in mysql is:
insert ignore into registerSmsUsers values(?,?,?)
When assuming you have unique key on mobile
You may check it here: How to 'insert if not exists' in MySQL?
Or here: http://dev.mysql.com/doc/refman/5.6/en/insert.html
Many of the proposed solutions (including yours) have a race condition that can cause a primary key or unique constraint violation. You code also have a possible SQL injection attack by concatenating SQL rather than using prepared statement parameters. Use SELECT...FOR UPDATE.
PreparedStatement ps = con.prepareStatement("SELECT name, email, mobile FROM registerSmsUsers WHERE mobile=? FOR UPDATE",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
ps.setString(1, mobile);
ResultSet rs = ps.executeQuery();
if (rs.next()) { // it exists already
rs.moveToCurrentRow();
rs.updateString(3, mobile);
rs.updateRow();
} else { // it does NOT exist
rs.moveToInsertRow();
rs.updateString(1, name);
rs.updateString(2, email);
rs.updateString(3, mobile);
rs.insertRow();
}
rs.close();
ps.close();
EDIT: Just make sure you have an index on registerSmsUsers.
CREATE INDEX registerSmsUsers_mobile_ndx ON registerSmsUsers(mobile)
or a unique contraint (which implicitly creates an index):
ALTER TABLE registerSmsUsers ADD CONSTRAINT registerSmsUsers_mobile_unq UNIQUE (mobile)
With an index, even with millions of records the update/insert will basically be instant.
EDIT2: Added cursor/result set options.
I think it would be better to create a stored procedure and then in that stored procedure you can first use the IF NOT EXISTS clause to check if the user exists using the select statement. If the user is not present you can insert the user in database.
Something like this:
IF NOT EXISTS(SELECT 1 FROM `registerSmsUsers` WHERE mobile= #mobile) THEN
BEGIN
INSERT INTO
`registerSmsUsers`
(
//column names
)
VALUES
(
//values
);
END;
END IF;
Also there is a INSERT IGNORE statement which you can use like this:
insert ignore into registerSmsUsers values(?,?,?)
if not exists(select * from registerSmsUsers where mobile='232323') <-- will check your mobile no
begin
insert into registerSmsUsers values(?,?,?)
end
This one is also an efficient way to check your method is also working fine but this also can be done
See difference is you will have only one query here
i hope this will help you thanks
[Edit]
Your questions answer
Ya there is a execution time diff between yours and mine query its depends upon a database size what you are using if you are using small size database (probably 1000 people) then you will not see any diff between your query and mine query but if your are using lakhs of users then your will have a performace issues check include execution plan in mysql you will get realtime difference between two
As requested, here is my tweaked version of brettw's answer:
import java.sql.*;
public class MySQLtest {
public static void main(String[] args) {
Connection con;
try {
con = DriverManager.getConnection(
"jdbc:mysql://192.168.1.3/zzzTest?" +
"useUnicode=yes&characterEncoding=UTF-8" +
"&user=root&password=whatever");
String newName = "Gord";
String newEmail = "gord#example.com";
String newMobile = "416-555-1212";
String sql =
"SELECT " +
"id, " +
"name, " +
"email, " +
"mobile " +
"FROM registerSmsUsers " +
"WHERE mobile = ? " +
"FOR UPDATE";
PreparedStatement pst = con.prepareStatement(
sql,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
pst.setString(1, newMobile);
ResultSet rs = pst.executeQuery();
if (rs.next()) {
rs.moveToCurrentRow();
rs.updateString("name", newName);
rs.updateString("email", newEmail);
rs.updateRow();
System.out.println("Existing row updated.");
}
else {
rs.moveToInsertRow();
rs.updateString("name", newName);
rs.updateString("email", newEmail);
rs.updateString("mobile", newMobile);
rs.insertRow();
System.out.println("New row inserted.");
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
Note that id is the Primary Key for the table: int(11) NOT NULL AUTO_INCREMENT

Creating tables in Oracle database by JDBC

I have problem with creating tables by JDBC controller on Oracle database.
When I create table by "creata table...." is ok. Table create and I see that table by SQL Developer. I have method to check if table with that name exist - and it works good.
So when I create table (I try to do commit, too - do not help), table appear in SQL developer but when i check by my method if that table exist i get 'false' (do not exist), when I restart database and run again, my method return 'true'.
I think is a problem with session but I don't now how to get over with that.
enter code here public void prepStatExecuteCreateTable(String name){
String createTable= "Create table "+ name +" (ID NUMBER(*, 0) NOT NULL PRIMARY KEY, CZAS NUMBER(*, 0) NOT NULL, OTWARCIE NUMBER(6, 2) NOT NULL , MAX_KURS NUMBER(6, 2) NOT NULL , MIN_KURS NUMBER(6, 2) NOT NULL , ZAMKNIECIE NUMBER(6, 2) NOT NULL , VOLUMEN NUMBER(*, 0) NOT NULL , FOREIGN KEY(czas) references CZAS(ID))";
PreparedStatement ps=null;
try{
ps = returnConnection().prepareStatement(createTable);
}catch(SQLException e){
System.out.println("Error with preperadStatement(create table): "+ e.getMessage());
}
try{
ps.execute();
returnConnection().commit();
ps.close();
closeConnection();
}
catch(SQLException e){
System.out.println("Error with execute: "+ e.getMessage());
}
}
public boolean ifExistTable(String tablename) throws SQLException{
String sql = "Select TABLE_NAME from user_tables where table_name='"+tablename.toUpperCase()+"' ";
System.out.println(sql);
ResultSet rs =null;
Statement ps = null;
try{
ps = returnConnection().createStatement();
}catch(SQLException e){
System.out.println("Error with preperadSatement(checking): "+ e.getMessage());
}
try{
rs=ps.executeQuery(sql);
while (rs.next()){
System.out.println (rs.getString(1)); // Print col 1
if(rs.getString(1).equals(tablename)){
return true;
}
}
}
catch(SQLException e){
System.out.println("Error with executing checking " +e.getMessage()+ " " + e.getStackTrace());
}
ps.close();
return false;
}
this is how I use in the Main method: (condDB is a object that has above methods)
enter code here String table_name="BBB";
System.out.println(conDB.ifExistTable(table_name));
conDB.prepStatExecuteCreateTable(table_name);
so if I run first, I get message "false" (table do not exist)
and is created (check by SQL developer, table with name 'BBB' appear)
when I run secondly I get message "false" and error message from second method:
Error with execute: ORA-00955: name is already used by an existing object
1) Your ifExistTable function really ought to be using bind variables rather than building the SQL statement using string concatenation if only to avoid SQL injection attacks.
2) Your ifExistTable function is running a query that uses the upper-case value of the tablename that is passed in. But then when you're fetching the data from rs, you're making a case-sensitive comparison with rs.getString(1).equals(tablename). At a minimum, that ought to be equalsIgnoreCase. But there should be no need to do the comparison at all in Java since your SQL statement is already doing it. If the ResultSet has a row, the table exists (or you can write the query as a COUNT(*) and check to see whether the row that is returned has a value of '1').
Perhaps when you created your stored procedure inside the package, you didn't close it with '/'
...
END;
/
so the connection is stucked and the resource is not liberated to be used by other query (which is actually another logical connection). commit will not work as you are performing a DDL sentence which could care less about commiting hehehe

Categories

Resources