SQLite is busy, Database is locked - java

I need help, I'm trying to insert something into the existing Database, but I can't get it going. I get The database file is locked (database is locked). I have tried closing the preparedStatement, but no luck. I used executeUpdate() instead executeQuery(), no help.
public class tableController {
Connection connection;
#FXML
private TextField txtId;
#FXML
private TextField txtName;
#FXML
private TextField txtLastName;
#FXML
private TextField txtAge;
#FXML
private TextField txtUsername;
#FXML
private TextField txtPassword;
#FXML
private Button save;
public tableController() {
connection = SQLiteConnection.connector();
if(connection == null) {
System.out.println("Test");
System.exit(1);
}
}
public boolean isDBConnected() {
try {
return !connection.isClosed();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
public void Insert(ActionEvent event) throws SQLException {
PreparedStatement preparedStatement = null;
ResultSet resultSet;
String query = "insert into employee (id, name, lastName, age, username, password) values (?,?,?,?,?,?)";
try {
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, txtId.getText());
preparedStatement.setString(2, txtName.getText());
preparedStatement.setString(3, txtLastName.getText());
preparedStatement.setString(4, txtAge.getText());
preparedStatement.setString(5, txtUsername.getText());
preparedStatement.setString(6, txtPassword.getText());
Alert aleret = new Alert(AlertType.INFORMATION);
aleret.setTitle("Information dialog");
aleret.setHeaderText(null);
aleret.setContentText("User has been created");
aleret.showAndWait();
preparedStatement.executeUpdate();
} catch (Exception e) {
// TODO: handle exception
JOptionPane.showMessageDialog(null, e);
e.printStackTrace();
} finally {
if(preparedStatement != null) {
preparedStatement.close();
}
}
}
}

I have found the solution.
#CL. was right, there was other connection object running in the background.
Problem was that I did not closed preparedStatement and resultSet when logging into the app.
PreparedStatement preparedStatement;
ResultSet resultSet;
String query = "select * from employee where username = ? and password = ?";
try {
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, user);
preparedStatement.setString(2, pass);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
preparedStatement.close(); // after closing this, it works
resultSet.close(); // closed this one also
return true;
} else {
return false;
}
} catch (Exception e) {
// TODO: handle exception
return false;
}

Related

What is the right way to deal with the PreparedStatement in the Java program flow?

There are two methods in which the PreparedStatement is used.
The first method is called in the second method.
First method:
protected List<String> findResultsByMandantId(Long mandantId) {
List<String> resultIds = new ArrayList<>();
ResultSet rs;
String sql = "SELECT result_id FROM results WHERE mandant_id = ?";
PreparedStatement statement = getPreparedStatement(sql, false);
try {
statement.setLong(1, mandantId);
statement.execute();
rs = statement.getResultSet();
while (rs.next()) {
resultIds.add(rs.getString(1));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return resultIds;
}
Second method:
protected void findResultLineEntityToDelete(Long mandantId, String title, String context) {
List<String> resultIds = findResultsByMandantId(mandantId);
String [] resultIdsArr = resultIds.toArray(String[]::new);
ResultSet rs;
//String sql = "SELECT * FROM resultline WHERE result_id in (SELECT result_id FROM results WHERE mandant_id =" + mandantId + ")";
String sql = "SELECT * FROM resultline WHERE result_id in (" + String.join(", ", resultIdsArr)+ ")";
PreparedStatement statement = getPreparedStatement(sql, false);
try {
statement.execute();
rs = statement.getResultSet();
while (rs.next()) {
if (rs.getString(3).equals(title) && rs.getString(4).equals(context)) {
System.out.println("Titel: " + rs.getString(3) + " " + "Context: " + rs.getString(4));
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
The class in which both methods are located extends the JDBCBaseManager.
JDBCBaseManager:
private final String url = "jdbc:mysql://localhost:3306/database";
private final String userName = "root";
private final String password = "";
private Connection connection = null;
private PreparedStatement preparedStatement = null;
private int batchSize = 0;
public JDBCBaseManager() {
// Dotenv env = Dotenv.configure().directory("./serverless").load();
// url = env.get("DB_PROD_URL");
// userName = env.get("DB_USER");
// password = env.get("DB_PW");
}
public void getConnection() {
try {
if (connection == null) {
connection = DriverManager.getConnection(url, userName, password);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public PreparedStatement getPreparedStatement(String sql, boolean returnGeneratedKeys) {
try {
if (connection == null) {
getConnection();
}
if (preparedStatement == null) {
if (!returnGeneratedKeys) {
preparedStatement = connection.prepareStatement(sql);
} else {
preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
connection.setAutoCommit(false);
}
}
return preparedStatement;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void closeConnection() {
try {
if (connection != null && !connection.isClosed()) {
System.out.println("Closing Database Connection");
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void startBatch(int batchSize) throws SQLException {
connection.setAutoCommit(false);
setBatchSize(batchSize);
}
public void commit() {
try {
if (connection != null && !connection.isClosed()) {
connection.commit();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int getBatchSize() {
return batchSize;
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
The ResultSet in the second method still contains the results from the first method.
I already tried to close the connection and open it again before the second method is executed, but then I get the errors:
java.sql.SQLException: No operations allowed after statement closed.
java.sql.SQLNonTransientConnectionException: No operations allowed
after connection closed.
Can you tell me how to deal with the statement correctly in this case? Is my BaseManager incorrectly structured?
Here lies the error
public JDBCBaseManager() {
private PreparedStatement preparedStatement = null;
public PreparedStatement getPreparedStatement(String sql, boolean returnGeneratedKeys) {
try {
......
if (preparedStatement == null) {
if (!returnGeneratedKeys) {
preparedStatement = connection.prepareStatement(sql);
} else {
preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
connection.setAutoCommit(false);
}
}
return preparedStatement;
You build the prepare statement only the first time the method getPreparedStatement is called because only the first time the field preparedStatement is null. Every next time you call the method getPreparedStatement you receive the previous preparedStatement from the previous SQL and not the new one.
Remove the check for if (preparedStatement == null) {
You need to build a new preparedStatement every time you want to execute a new SQL.

try-with-resources JDBC with multiple resources and an else statement

This is a method to add a new planet to an observablelist of customers.
I am wondering if I am using the try with resources correctly and if the auto-close is working.
public static Customer addPlanet(Customer customer) {
String query1 = "Select * from planet where planet=? AND universeID=?";
String query2 = "INSERT INTO planet (planet,universeID) VALUES(?,?)";
try (PreparedStatement statement = (PreparedStatement) Database.connection.prepareStatement(query1);
PreparedStatement statement2 = (PreparedStatement) Database.connection.prepareStatement(query2)) {
statement.setString(1, customer.getPlanet());
statement.setString(2, Integer.toString(customer.getUniverseID()));
try (ResultSet rs = statement.executeQuery()) {
if (rs.next()) {
int planetId = rs.getInt(1);
customer.setPlanetID(planetId);
return customer;
} else {
statement2.setString(1, customer.getPlanet());
statement2.setInt(2, customer.getUniverseID());
statement2.executeUpdate();
return addPlanet(customer);
}
} catch (SQLException e) {
e.printStackTrace();
return null;
}
} catch (SQLException e) {
e.printStackTrace();
}
return customer;
}
My question is, does this part need to be enclosed in a try-catch block or does it get closed automatically.
statement2.executeUpdate();
It gets closed. Anything in the try gets closed at the end if they are AutoCloseable.

How to fix ORA-01008 : Not all variables bound

I have a problem with this piece of code. When I pass user and pass arguments to isLogin fucntion it throws ORA-01008 errror. I am connected to Oracle database using jdbc.
public boolean isLogin(Connection conn, String user, String pass) throws SQLException{
String sql = "SELECT * FROM PRACOWNIK WHERE imie =? AND nazwisko =? ";
PreparedStatement stmt;
ResultSet rs;
try {
stmt = conn.prepareStatement(sql);
stmt.setString(1, user);
stmt.setString(2, pass);
rs = stmt.executeQuery(sql);
if(rs.next()){
return true;
}
else {
return false;
}
} catch (SQLException e){
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error ");
alert.setContentText(e.getMessage());
alert.showAndWait();
return false;
}
}
I use this function in Controller class
public class Controller implements Initializable{
public Pracownik pracownik = new Pracownik();
#FXML
private Label isConnected;
#FXML
private TextField txtUsername;
#FXML
private TextField txtPass;
private Connection conn;
// private ObservableList<Pracownik> lista = FXCollections.observableArrayList();
public void initialize(URL url, ResourceBundle rb){
conn = DBConnection.getConnection();
// lista = new Pracownik().getAll(conn);
}
public void login(ActionEvent event){
try {
if(pracownik.isLogin(conn, txtUsername.getText(), txtPass.getText())){
isConnected.setText("Correct");
}
else{
isConnected.setText("False");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
And this is a error message
Caused by: Error : 1008, Position : 0, Sql = SELECT pesel FROM PRACOWNIK WHERE imie =:1 AND nazwisko =:2 , OriginalSql = SELECT pesel FROM PRACOWNIK WHERE imie =? AND nazwisko =? , Error Msg = ORA-01008: not all variables bound
When I use normal Select query just to print the table everything is fine.
You should NOT specify the SQL query again. It's already specified. Change the line:
rs = stmt.executeQuery(sql); // method from java.sql.Statement
to:
rs = stmt.executeQuery(); // method from java.sql.PreparedStatement
The first method does not take parameters into consideration and runs the SQL "as is"... and therefore you get the error you mention.

Login doesn't work even if data is present in SQLite database [duplicate]

This question already has answers here:
Multiple returns: Which one sets the final return value?
(7 answers)
Closed 5 years ago.
I have a database and it has a table user which consists of many attributes like name ,email,etc. Also it has username and password in VARCHAR datatype. I wrote two classes LoginModel and Controller. controller has method loginit through which it checks if login method from LoginModel returns true or not. I am not able to find out why LoginModel always returns false. Please help.
Here are my methods :
from class LoginModel
public boolean login(String userid, String userpass) throws SQLException {
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String query = "SELECT * FROM user WHERE username = ? AND password = ?";
try{
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1,userid);
preparedStatement.setString(2,userpass);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
return true;
}
else {
// System.out.println(resultSet.next());
return false;
}
}
catch (Exception e){
return false;
}
finally {
preparedStatement.close();
resultSet.close();
return false;
}
}
from class Controller
public void loginit() throws SQLException {
String userid = uid.getText();
String userpass = upass.getText();
try {
if (loginmodel.login(userid, userpass)) {
lblstatus.setText("YES");
}
else
lblstatus.setText("Invalid");
} catch (SQLException e) {
lblstatus.setText("No");
e.printStackTrace();
}
}
It is a JavaFX application. userid and userpass are ids of text-field and password-field respectively. lblstatus is label which always shows Invalid, can't figure out why!
Here is snapshot of my database
remove return false from the finally block. It will executed in case of execption and in case you get no exception.
finally {
preparedStatement.close();
resultSet.close();
return false;
}
Change your code to:
public boolean login(String userid, String userpass) throws SQLException {
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String query = "SELECT * FROM user WHERE username = ? AND password = ?";
try{
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1,userid);
preparedStatement.setString(2,userpass);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
return true;
}
else {
// System.out.println(resultSet.next());
return false;
}
}
catch (Exception e){
return false;
}
finally {
preparedStatement.close();
resultSet.close();
}
return false;
}

radio button show values in combo box

I confused with this if-else because I'm new in Java & MySQL and I tried to make it by myself.
public Menu() {
initComponents();
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/restaurant", "root", "");
System.out.println("ODBC Connection Successful");
showCategory();
} catch (ClassNotFoundException | SQLException e) {
System.out.println("ODBC Connection Failed" + e);
}
}
if - else
private void showCategory() {
try {
Statement stmt;
stmt = con.createStatement();
if (rbMFood.isSelected()) {
ResultSet rs = stmt.executeQuery("SELECT * FROM menu_cat WHERE type_id = 'TY02'");
while (rs.next()) {
cmbMCat.addItem(rs.getString("menu_cat"));
}
} else {
ResultSet rs = stmt.executeQuery("SELECT * FROM menu_cat WHERE type_id = 'TY01'");
while (rs.next()) {
cmbMCat.addItem(rs.getString("menu_cat"));
}
}
} catch (Exception e) {
}
}
Radio Button
private void rbMFoodActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
type = "Food";
}
private void rbMDrinkActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
type = "Drink";
}
And I declare the function in the end of the program
private String type;
When I click drink / food, the category still drink's category.
The database
Any help would be greatly appreciated!
You are using rs.getString("menu_cat") But the format is rs.getString(<Column Name>) But you are using rs.getString(<Table Name>) As "menu_cat" is name of the table and not the name of the column.
AFTER POSTING CONSTRUCTOR
What I see from the code you have posted, is that You have called showCategory() in the constructor. This method is responsible for populating the JComboBox cmbMCat. Now the cmbMCat is being populated when you are creating the new Menu. After that the items list of the cmbMCat does not change.
So, What I suggest is that you call the showCategory() from the rbMFoodActionPerformed and rbMDrinkActionPerformed methods. I hope this will solve your problem.
Also add cmbMCat.removeAllItems() before Statement stmt; to remove all the items that are there in the cmbMCat and reset it with a fresh list of items.
After comment regarding the if-else
Change the showCatagory() as below:
private void showCategory() {
cmbMCat.removeAllItems();
try {
PreparedStatement stmt; //Used Prepared statement
String sql = "SELECT * FROM menu_cat WHERE type_id = ?";
stmt = con.prepareStatement(sql);
if (type.equals("Drink")) {
stmt.setString("TY01");
} else {
stmt.setString("TY02");
}
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
cmbMCat.addItem(rs.getString("menu_cat"));
}
}
} catch (Exception e) {
}
}
Also note that you eventListener code should be:
private void rbMFoodActionPerformed(java.awt.event.ActionEvent evt){
type = "Food";
showCategory();
}
private void rbMDrinkActionPerformed(java.awt.event.ActionEvent evt){
type = "Drink";
showCategory();
}

Categories