I am trying to Auto create SQL tables on first run, and haven't found any good tutorial on google. Does anyone have a suggestion or can explain it to me. My class so far looks like: http://pastebin.com/6u8yFWrt
In Mysql you can do:
CREATE TABLE tablename IF NOT EXISTS...
This will, as the name says, create the table if there is no table with the same name, described here. If you run it whenever you open the connection to the database, you should be fine.
BUT this is no guarantee that the existing table has the format you want! If you change the definition of the table halfway through the process, because you want an extra column, you will need to delete the existing table fist, for the changes in the query to have an effect.
I think you should use JPA and Hibernate instead. Youre probably in for quite a journey until you get the hold of it but I think it is worth the effort.
Related
I currently have a method in my Java program, using JDBC that checks if a specific table exists in a MySQL database. I had a logic error where the DatabaseMetaData.getTables() method was returning a same-named table from a different database, and I've now solved that by specifying the catalog in the statement as seen below (table represents the table name I'm looking for).
ResultSet tables = connectionToDatabase().getMetaData().getTables("snakeandladder", null, table, null);
However, after doing some research, I saw a lot of people recommending to use Show Tables instead, but not actually explaining why to use Show tables over the above.
Can someone explain to me the limitations of using the statement above and why Show Tables would be a better option?
Thank you!
DatabaseMetaData.getTables() is more portable, most of the databases (not only MySQL) should be able to provide information through defined API.
On the other hand using MySQL specific query "show tables;" may cause more harm than good:
you introduce a query string which can be exploited by an attacker, also the code now contains a statically compiled query string.
if ever the database provider will change, so the code will have to be updated (again portability)
I am using Hibernate with MSSQL server writing the software that integrates with an existing database. There is an instead of insert trigger on the table that I need to insert into and it messes up ##Identity, which means on Hibernate's save I can't get the id of inserted row. I can't control the trigger (can't modify it). I saw this question, but it involves procedures, which my trigger does not have, so I thought my question is different enough. I can't post the whole trigger, but hopefully I can post enough to get the point across:
CREATE TRIGGER TrigName ON TableName
INSTEAD OF INSERT
AS
SET XACT_ABORT ON
BEGIN TRANSACTION
-- several DECLARE, SET statements
-- a couple of inserts into other tables for business logic
-- plain T-SQL statements without procedures or functions
...
-- this is the actual insert that i need to perform
-- to be honest, I don't quite understand how INSERTED table
-- was filled with all necessary columns by this point, but for now
-- I accept it as is (I am no SQL pro...)
INSERT INTO ClientTable (<columns>)
SELECT <same columns> from INSERTED
-- a couple of UPDATE queries to unrelated tables
...
COMMIT TRANSACTION;
I was wondering if there is a reliable way to get the id of the row being inserted? One solution I thought of and tried to make is to install an on insert trigger on the same table that writes the newly inserted row into a new table I added to the db. I'd use that table as a queue. After transaction commit in Hibernate I could go into that table and run a select with the info I just inserted (I still have access to it from the same method scope), and I can get the id and finally remove that row. This is a bulky solution, but best I can come up with so far.
Would really appreciate some help. I can't modify existing triggers and procedures, but I can add something to the db if it absolutely does not affect existing logic (like that new table and a on insert trigger).
To sum up: I need to find a way to get the ID of the row I just inserted with Hibernate's save call. Because of that instead of insert trigger, hibernate always returns identity=0. I need to find a way to get that ID because I need to do the insert in a few other tables during one transaction.
I think I found an answer for my question. To reply to #SeanLange's comment: I can't actually edit insert code - it's done by another application and inquiry to change that will take too long (or won't happen - it's a legacy application). What I did is insert another trigger on insert on the same table. Since I know the order of operations in the existing instead of insert trigger I can see that the last insert operation will be in the table I want so that means my on insert trigger will fire right after that. In the scope of that trigger I have access to inserted table out of which I pull out the id.
CREATE TRIGGER Client_OnInsert ON myClientTable
FOR INSERT
AS
BEGIN
DECLARE #ID int;
SET #ID = (select ClientID from inserted);
INSERT INTO ModClient (modClientId)
OUTPUT #ID
VALUES (#ID);
END
GO
Then in Hibernate (since I can't use save() anymore), I use a NativeQuery to do this insert. I set parameters and run the list() method of NativeQuery, which returns a List where the first and only argument is the id I want.
This is a bulky way, I know. If there is anything that's really bad that will stand out to people - please let me know. I would really appreciate some feedback on this. However, I wanted to post this answer as a potential answer that worked so far, but it does not mean it's very good. For this solution to work I did have to create another small table ModClient, which I will have to use as a temp id storage for this exact purpose.
I need to insert a record to table if the record doesn't exist, and to update a record if the record exists in the table.
Of course, I can write:
p-code:
SELECT * FROM table1 WHERE id='abc' by JDBC
if(exists)
UPDATE table1 SET ... WHERE id='abc' by JDBC;
else
INSERT INTO table1... by JDBC;
However, I don't think the code is elegant.
Alternatively, I can also write it in this way:
p-code:
int row = Statement.executeUpdate("INSERT INTO table1...", 2);
if(row==0)
update table1 SET ... WHERE id='abc' by JDBC;
Do you think the latter way is better and faster? Thanks!
EDIT: in MYSQL
It depends on what type of database your are using and whether or not you can take advantage of database specific features. MySQL for instance lets you do the following:
INSERT INTO territories (code, territory) VALUES ('NO', 'Norway')
ON DUPLICATE KEY UPDATE territory = 'Norway'
However, the above is not standard (SQL-92) compliant. That is, it will most likely not work on all databases. In other words, you would have to stick with the code as you have written it. It might not look that elegant, but it is probably the most safe solution to go with.
You might want to look at using the DBMS to do the check within a single statement i.e. use the SQL EXISTS condition: WHERE EXISTS or WHERE NOT EXISTS
Maybe the database you are using has an insert or update feature which solves this automatically for you. In DB2 you can use MERGE INTO for example. See here
This is probably the reason to switch to one of popular ORM solutions (Hibernate, Toplink, iBatis). These tools "know" various SQL dialects and optimise your queries accrodingly.
I need the sample program in Java for keeping the history of table if user inserted, updated and deleted on that table. Can anybody help in this?
Thanks in advance.
If you are working with Hibernate you can use Envers to solve this problem.
You have two options for this:
Let the database handle this automatically using triggers. I don't know what database you're using but all of them support triggers that you can use for this.
Write code in your program that does something similar when inserting, updating and deleting a user.
Personally, I prefer the first option. It probably requires less maintenance. There may be multiple places where you update a user, all those places need the code to update the other table. Besides, in the database you have more options for specifying required values and integrity constraints.
Well, we normally have our own history tables which (mostly) look like the original table. Since most of our tables already have the creation date, modification date and the respective users, all we need to do is copy the dataset from the live table to the history table with a creation date of now().
We're using Hibernate so this could be done in an interceptor, but there may be other options as well, e.g. some database trigger executing a script, etc.
How is this a Java question?
This should be moved in Database section.
You need to create a history table. Then create database triggers on the original table for "create or replace trigger before insert or update or delete on table for each row ...."
I think this can be achieved by creating a trigger in the sql-server.
you can create the TRIGGER as follows:
Syntax:
CREATE TRIGGER trigger_name
{BEFORE | AFTER } {INSERT | UPDATE |
DELETE } ON table_name FOR EACH ROW
triggered_statement
you'll have to create 2 triggers one for before the operation is performed and another after the operation is performed.
otherwise it can be achieved through code also but it would be a bit tedious for the code to handle in case of batch processes.
You should try using triggers. You can have a separate table (exact replica of your table of which you need to maintain history) .
This table will then be updated by trigger after every insert/update/delete on your main table.
Then you can write your java code to get these changes from the second history table.
I think you can use the redo log of your underlying database to keep track of the operation performed. Is there any particular reason to go for the program?
You could try creating say a List of the objects from the table (Assuming you have objects for the data). Which will allow you to loop through the list and compare to the current data in the table? You will then be able to see if any changes occurred.
You can even create another list with a object that contains an enumerator that gives you the action (DELETE, UPDATE, CREATE) along with the new data.
Haven't done this before, just a idea.
Like #Ashish mentioned, triggers can be used to insert into a seperate table - this is commonly referred as Audit-Trail table or audit log table.
Below are columns generally defined in such audit trail table : 'Action' (insert,update,delete) , tablename (table into which it was inserted/deleted/updated), key (primary key of that table on need basis) , timestamp (the time at which this action was done)
It is better to audit-log after the entire transaction is through. If not, in case of exception being passed back to code-side, seperate call to update audit tables will be needed. Hope this helps.
If you are talking about db tables you may use either triggers in db or add some extra code within your application - probably using aspects. If you are using JPA you may use entity listeners or perform some extra logic adding some aspect to your DAO object and apply specific aspect to all DAOs which perform CRUD on entities that needs to sustain historical data. If your DAO object is stateless bean you may use Interceptor to achive that in other case use java proxy functionality, cglib or other lib that may provide aspect functionality for you. If you are using Spring instead of EJB you may advise your DAOs within application context config file.
Triggers are not suggestable, when I stored my audit data in file else I didn't use the database...my suggestion is create table "AUDIT" and write java code with help of servlets and store the data in file or DB or another DB also ...
I'm working at refactoring a lot of test code that uses a local host mysql. As can be imagined this is not optimal so I'm replacing mysql with hsqldb (for testing purposes, production still uses mysql). So far this is going (somewhat) smoothly as the code uses only standard sql. Now, however, I've run into a snag.
The code polls a table to get its last update time and send it to all observers. The code uses the mysql specific (AFAIK) syntax show table status from someDb like tableName and then pulls the update_time column from the result set.
I need to implement the same thing in HSQLDB and I haven't been able to find anything.
I've looked at the java.sql.DatabaseMetaData class to see if there is anything there that I can use to no avail.
I've been unable to format a google question narrow enough to be useful and so I turn to stackoverflow!
So far I've haven't found anything about HSQLDB:s special tables either.
Up to version 2.1 RC4, HSQLDB does not have built-in functionality for this feature. You can define triggers in SQL on a given table which store the update time in another user-defined table. This example stores the last INSERT time. Other triggers (AFTER UPDATE or AFTER DELETE) should be defined to store the last UPDATE or DELETE time.
create table updatetime (table_name varchar(128) PRIMARY KEY, update_time timestamp );
create trigger trig after insert on sometable
update updatetime set update_time = current_timestamp
where updatetime.table_name = 'SOMETABLE'
i dont know if im right but afaik there was an Infomration Scheme in HSQL:
check the Information Scheme section in the HSQL Manual (http://hsqldb.org/doc/2.0/guide/databaseobjects-chapt.html)
There ought to be some views in this scheme holding all the metadata.
try if you can find a View named "TABLES" there, and check if you find the information you're seeking in some column of this view.
Update: found this question with a perfect answer:
How to see all the tables in an HSQLDB database?