I have a database with table "Customers". I am currently creating a customer application where administrators should be able to create/delete etc customers. so I want to have one safty in case you delete a customers by mistake. My question are, what is the best way to restore a customer if being deleted?
I was thinking of just having an own table for deleted customers but dont know if there are other ways to achive this.
One way to do this is to add a boolean active column to your Customers table
create table Customers (
firstname varchar(20),
secondname varchar(20),
active Boolean default true
);
And then when you select your records
select * from Customers where active = true;
Then, rather than deleting entries from your customers table, you can just set active to false
Use “soft delete”. That means you don’t really ever delete anything, instead have a flag on each row you can toggle to show a customer is not active. Then you can have a view that shows only non-deleted customers that the code not concerned with undeleting can use.
You should be taking database backups.
Backups are your "first line of defense" - against accidental deletions ... and against anything else that could happen (like a hard disk crash, for example. Or a meteor crash.).
Another approach is to assign a [trigger] to any delete (or, for that matter, to "insert" and "update" statements as well). You can prevent deletion (if you wish), and you'll have a record of who tried to delete.
Here is an example: http://rpbouman.blogspot.com/2011/10/mysql-hacks-preventing-deletion-of.html
Finally, the best approach might be to never delete at all: just create a new "status" column. Set the initial value to "ACTIVE", and "deleted" value to "DELETED".
I agree totally with what #paulsm4 wrote.
I would also add that you could consider using Hibernate Envers.
Envers will create new tables that will record the changing state of audited tables.
An approach is to not actually delete the customer and add an additional status column.
In the business layer you will be able to display all users with status != DELETED.
OBS:
If you actually need to delete them from the database, you can make a cron that will scan all customers with status deleted and deletes them after x days.
Related
I have a Postgres table named mytable which I am using from JPA/Hibernate entity to manage it.
The table has a column name mycolumn with default value set as FALSE.
Now there will be many concurrent update to that column and I want only to update if and only if value is FALSE, and once it is updated to TRUE by any of one, no other concurrent requests must be able to update it, never ever, resulting in something like 'Value has been already updated and you can not update it.'
AFAIK Locking is not going to help with this.
How to handle this with JPA/Hibernate in concurrent situation?
Thanks
Edit: revise title
I am using Spring+Hibernate for my application. I have a few CRUD operations. Before inserting, I need to check if a similar entry is already in the database, if yes it should not be inserted.
For eg: If I am trying to create a Department, before inserting the row, I should check if a department with the same name already exist or not. If yes, the method returns error message.
Now, I know the unique key constraint can be set on the column to do the check. But, I want to know if there is any other way to do this.
The only way I can think of is first fetching all the departments from the database and check against each object.
Please let me know if there is any other way.
The only way I can think of is first fetching all the departments from the database and check against each object.
You don't need to fetch all departments form the database. It should be enough to search the database for the department with the name you want to insert. Since the name should have a unique key anyways it should be fast enough.
If your #Id attribute is department name, then the saveOrUpdate API of Hibernate will check if an object with that id is already present in the DB. If so it will update, else it will create a new entry. Hope this should help you. See this link.
You can try find object from database by "get" method:
Cat cat = (Cat) sess.get(Cat.class, id);
If received object is null, you can add new.
Also for performance better use query with "count" predicate, for avoid whole object loading.
I have a question.
So I have a add functionality where the user can add cars to the database. How do I do a check whilst adding the car, so that if the car does exist-the data is overwritten, instead of an error messaging like 'Duplicate error' appearing?
So I have...
INSERT INTO Cars VALUES (1, "AUDI R8", 10);
How do I do it so that if a user inputs (1, "BMW X5, 15), it overwrites the current data?
How would I have an INSERT INTO and UPDATE STATEMENT at the same time? Also how do I make use of transactions here?
Many thanks
MySQL has a REPLACE statement for this kind of cases:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted [...]REPLACE is a MySQL extension to the SQL standard. It either inserts, or deletes and inserts.
Check the reference for the REPLACE statement.
Well, the best solution for this problem are the TRIGGERS.
Triggers allow you to separate the application layer from the the database.
In your case you need to launch an error, so this is a trigger called "passive", that reacts automatically only if the condition is violated.
Take a look a this: https://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html or various related docs.
Maybe is not the best solution, but u can do a SELECT first, and after do an UPDATE or a simply INSERT, depends of the case.
Consider am using java , struts, hibernate and oracle. How can i prevent duplicate entries stored in database. One way is to make field as Unique . For example i am entering country "USA" in jsp page,USA is already available means how can i prevent it. Please let me know.
Regards,
sara
You should always indeed put a unique constraint on fields which must stay unique. This will, however, lead to a cryptic exception at commit time. If you want to be more user-friendly, you should check if the entry already exists (using a query) before inserting it, and display a useful and readable error message to the user if the entry already exists.
This still allows two concurrent users to check at the same time, then insert at the same time, but it greatly reduces the probability, and the unique constraint makes sure that one of the commits will fail, leaving your database in a consistent state.
Query your database whether it already contains USA or not. If it does, then don't store it. If not, then do.
Add a unique index to your database table on the country column.
Additionally you can annotate the country attribute of your hibernate object with #Column(unique=true).
I have an existing application that I am working w/ and the customer has defined the table structure they would like for an audit log. It has the following columns:
storeNo
timeChanged
user
tableChanged
fieldChanged
BeforeValue
AfterValue
Usually I just have simple audit columns on each table that provide a userChanged, and timeChanged value. The application that will be writing to these tables is a java application, and the calls are made via jdbc, on an oracle database. The question I have is what is the best way to get the before/after values. I hate to compare objects to see what changes were made to populate this table, this is not going to be efficient. If several columns change in one update, then this new table will have several entries. Or is there a way to do this in oracle? What have others done in the past to track not only changes but changed values?
This traditionally what oracle triggers are for. Each insert or update triggers a stored procedure which has access to the "before and after" data, which you can do with as you please, such as logging the old values to an audit table. It's transparent to the application.
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:59412348055
If you use Oracle 10g or later, you can use built in auditing functions. You paid good money for the license, might as well use it.
Read more at http://www.oracle.com/technology/pub/articles/10gdba/week10_10gdba.html
"the customer has defined the table structure they would like for an audit log"
Dread words.
Here is how you would implement such a thing:
create or replace trigger emp_bur before insert on emp for each row
begin
if :new.ename = :old.ename then
insert_audit_record('EMP', 'ENAME', :old.ename, :new.ename);
end if;
if :new.sal = :old.sal then
insert_audit_record('EMP', 'SAL', :old.sal, :new.sal);
end if;
if :new.deptno = :old.deptno then
insert_audit_record('EMP', 'DEPTNO', :old.deptno, :new.deptno);
end if;
end;
/
As you can see, it involves a lot of repetition, but that is easy enough to handle, with a code generator built over the data dictionary. But there are more serious problems with this approach.
It has a sizeable overhead: an
single update which touches ten
field will generate ten insert
statements.
The BeforeValue and AfterValue
columns become problematic when we
have to handle different datatypes -
even dates and timestamps become
interesting, let alone CLOBs.
It is hard to reconstruct the state
of a record at a point in time. We
need to start with the earliest
version of the record and apply the
subsequent changes incrementally.
It is not immediately obvious how
this approach would handle INSERT
and DELETE statements.
Now, none of those objections are a problem if the customer's underlying requirement is to monitor changes to a handful of sensitive columns: EMPLOYEES.SALARY, CREDIT_CARDS.LIMIT, etc. But if the requirement is to monitor changes to every table, a "whole record" approach is better: just insert a single audit record for each row affected by the DML.
I'll ditto on triggers.
If you have to do it at the application level, I don't see how it would be possible without going through these steps:
start a transaction
SELECT FOR UPDATE of the record to be changed
for each field to be changed, pick up the old value from the record and the new value from the program logic
for each field to be changed, write an audit record
update the record
end the transaction
If there's a lot of this, I think I would be creating an update-record function to do the compares, either at a generic level or a separate function for each table.