I'm trying to add designation and its salary using a JDBC transaction.
The problem is this throws an exception about duplicate key.
This is the first time I put some invalid data in salary columns and after that everything is correct. It shows duplicate key exception for designation id
but the designation id is not stored already and not even for first attempt.
The first transaction that is invalid is rolled back, but storing on next time it shows duplicate key exception.
Below is my code:-
public boolean addDesignation(ObservableList nodeList) throws SQLException {
Connection demo = getConnection();
demo.setAutoCommit(false);
Savepoint savePoint = demo.setSavepoint("savePoint");
try {
PreparedStatement addDesig = demo.prepareStatement(
"INSERT INTO `designation`(`desig_id`,`dept_id`,`desig_name`,`desig_desc`) VALUES (?,?,?,?)");
PreparedStatement addSal = demo.prepareStatement("INSERT INTO `salary` "
+ "(`desig_id`, `basic`, `house_rent`, `conveyance`, `medical`, `dearness`,`others_allowances`,"
+ " `income_tax`, `pro_tax`, `emp_state_insu`, `absence_fine`, `others_deductions`, `month`)"
+ " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)");
addDesig.setString(1 , nodeList.get(0).toString());
addDesig.setString(2, nodeList.get(1).toString());
addDesig.setString(3, nodeList.get(2).toString());
addDesig.setString(4, nodeList.get(3).toString());
addDesig.executeUpdate();
addSal.setString(1, nodeList.get(0).toString());
addSal.setInt(2, Integer.parseInt(nodeList.get(4).toString()));
addSal.setInt(3, Integer.parseInt(nodeList.get(5).toString()));
addSal.setInt(4, Integer.parseInt(nodeList.get(6).toString()));
addSal.setInt(5, Integer.parseInt(nodeList.get(7).toString()));
addSal.setInt(6,Integer.parseInt(nodeList.get(8).toString()));
addSal.setInt(7,Integer.parseInt(nodeList.get(9).toString()));
addSal.setInt(8, Integer.parseInt(nodeList.get(10).toString()));
addSal.setInt(9, Integer.parseInt(nodeList.get(11).toString()));
addSal.setInt(10, Integer.parseInt(nodeList.get(12).toString()));
addSal.setInt(11, Integer.parseInt(nodeList.get(13).toString()));
addSal.setInt(12, Integer.parseInt(nodeList.get(14).toString()));
addSal.setString(13, nodeList.get(15).toString());
addSal.executeUpdate();
demo.commit();
return true;
} catch (SQLException ex) {
demo.rollback(savePoint);
Logger.getLogger(DatabaseHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
these are two tables and im trying to add that data in my first attempt failed but not store due roll back
There are 2 INSERT statements in your code.
The 1st for designation table:
"INSERT INTO `designation`(`desig_id`,`dept_id`,`desig_name`,`desig_desc`) VALUES (?,?,?,?)"
here it looks like desig_id is the primary key (maybe autoincrement in which case you must not supply a value at all).
Are you sure the value that you supply for this column does not already exist in the table?
The 2nd for the salary table:
"INSERT INTO `salary` " + "(`desig_id`, `basic`, `house_rent`, `conveyance`, `medical`, `dearness`,`others_allowances`," + " `income_tax`, `pro_tax`, `emp_state_insu`, `absence_fine`, `others_deductions`, `month`)" + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"
in this case it is not clear since you did not post the CREATE statement of the table, which is the primary key.
So you have to check, if the value (or values if it's a multi column key), violate the uniqueness of the key.
I have some trouble removing specific users from my SQLite database on my Android device. I made a simple method to delete a table row where table.name equals first input and table.surname equals second input.
Here is my method:
void deleteUser(db_operations opt, String name, String surname) {
SQLiteDatabase sdb = opt.getWritableDatabase();
if(validate(name, surname) == true) {
name = name.replaceAll("\\s+",""); surname = surname.replaceAll("\\s+","");
try {
String DELETE_USER = "DELETE FROM " + tb_users.tb_name + " WHERE " + tb_users.name + "='" + name + "' AND " + tb_users.surname + "='" + surname + "'";
sdb.execSQL(DELETE_USER);
sdb.close();
System.out.println("Deletion SUCCESS!");
} catch (SQLException e) {
System.out.println("Deletion FAILED!");
}
}
}
If I execute a DELETE FROM myTableName statement, every user is removed from the table and from my ScrollView which is ok, but if I execute the above method to remove a specific user, output gives:
Deletion SUCCESS!
but my table still has the record. The record also remains in my ScrollView list (made with LinearLayouts). The list is built dynamically. I've already checked if the data is good or not before my SQLite execution starts and it looks ok. I can't figure out why my method doesn't work. Maybe I've missed something.
(Posted on behalf of the question author).
I got it working. I found out that my validation method was returning false output all the time (I made a typo in one of the conditions), that's why my method never got a chance to execute. Thanks for a reminder to use logs. Was able to track my typo.
I have a Spring application with a update API endpoint for a Postgres database. The user can submit information and updates will be reflected in the database. The user only submits what they have to update. For example consider the following object:
class Dog {
String name;
int age;
String breed;
// Attributes and getters/setters...
}
When the user submits a update request, they only send the information they wish to update, such as only name and breed. I have the following function that updates the database with information:
public void update(String name, int age, String breed, JdbcTemplate template) {
UpdateBuilder query = new UpdateBuilder();
query.from("DogTable");
boolean updated = false;
if (name != null) {
query.set("name" + " = '" + name + "'");
updated = true;
}
if (age != null) {
query.set("age" + " = '" + age + "'");
updated = true;
}
if (breed != null) {
query.set("breed" + " = '" + breed + "'");
updated = true;
}
// And so on...
if (updated) {
query.set("UpdatedTime" + " = '" + new Date() + "'");
}
query.where("someKey" + " = '" + someId + "'");
template.update(query.toString());
}
(The query.set() stuff is just a helper class that builds a query string)
As you can see, this gets messy with all the "is the name given, is the age given?" checks. That leads to my question: Is there a data driven approach to do this? What I would like to be able to do is:
myJdbcTemplate.update(ListOfObjectsToUpdate, "TableName");
Simply, the JDBC template would see what I have provided it, and would proceed to update the provided table with that information. Is this even possible? I realize that building queries using strings is bad, but PreparedStatements don't look much better in code (not to mention, they don't solve this issue).
You can use the COALESCE function for this purpose - add user value as well and existing value and if the user value is not null (intended update) it well be set as the new value.
Similar to this -
UPDATE "user" SET alternate_contact_name = COALESCE(<user value>, alternate_contact_name)
This is a MySQL query but COALESCE works same way in Postgresql
The user value will be set and new value if it is not null. When it is null and original value of column is not null, the original value if picked. If both are null then it doesn't matter.
WIth this you can simply pass all parameters and avoid building query in an untidy way.
I wanted to make sure there were no duplicate timestamps in my table but then I found that it may be problematic if I simply use UNIQUE, because right now my table has:
_ID field (autoincrement)
Account ID (integer, links to an account table)
Category ID (integer, links to a category table)
Value (the value of this category for this account)
Timestamp (the timestamp of this value of this category for this account)
Is there a way to designate the timestamp field as unique within the context of the account ID and category ID? As in, it should not be possible to put in two values for a single timestamp, with respect to account and category. But the timestamp may show up multiple times in the table as a whole, either because it corresponds to other Categories and/or Accounts.
you can create a trigger and check whatever constraint you need:
#Override
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
database.execSQL("CREATE TRIGGER UNIQUE_TIMESTAMP_TRIGGER " +
"AFTER INSERT ON MY_TABLE FOR EACH ROW " +
"BEGIN " +
" SELECT RAISE(ABORT, 'Timestamp not unique') WHERE " +
" EXISTS(SELECT TIMESTAMP MY_TABLE T2 " +
" WHERE T2.TIMESTAMP = NEW.TIMESTAMP AND T2.ACCOUNT_ID = NEW.ACCOUNT_ID) " +
"END; ");
}
I run the below code in multithreaded program and get exception:-
org.hibernate.exception.ConstraintViolationException: ERROR: duplicate
key value violates unique constraint "value_pkey"
#Stateless
#TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED)
public class GetHelloBean{
#PersistenceContext(unitName = "test-unit")
private EntityManager entityManager;
public Hello<?> insertOrUpdateHello(Hello<?> value) {
Hello<?> existing = null;
try {
existing = this.entityManager.find(Hello.class,
value.getKey());
if (existing != null) {
value = this.entityManager.merge(value);
} else {
this.entityManager.persist(value);
}
this.entityManager.flush();
} catch (Exception e) {
this.logger.error(" value not saved : " + value.toString()
+ " of class " + value.getClass() + ":" + e.getMessage());
}
//
return value;
}
}
Can someone explain why and how can i handle this?
This error may be caused by a race condition in your code. If two or more threads are trying to update a Hello entity with the same key, they may both have a null returned from find and will attempt to persist the entity. Consequently only the "fastest" of the threads will succeed, while others encounter the constraint violation.
If value.getKey() is the primary key of the Hello entities, doing only a merge(...) should be sufficient. Hibernate will check if the entity already exists in the db or the cache and executes an INSERT or UPDATE depending on that. Concurrent executions may still yield unexpected results though (perceived out of order updates).
If it is not the primary key of the Hello entities maybe this answer can help you.