ibatis check for exist before creating value - mysql

I have a property definition table and second one that holds the actual property values:
table propdef: id, name, description
table props: id, propdefid, userid, value
This way i can dynamically create properties for my users. When I want to update a property for a user I have to check the props table if a propdefid/userid row exists and then either use update or create on this.
Right now I am first querying the db and then deciding on what to do in my java code. Is there a way to do that in the ibatis sqlmap - without extra logic in my java code?
I am using mysql as db.

before you go any farther, you need to stop and read this article: http://tonyandrews.blogspot.com/2004/10/otlt-and-eav-two-big-design-mistakes.html
if you still decide that EAV is the way to go, there is still hope. i can't advise at the ibatis/java level, but i can tell you to look at INSERT ... ON DUPLICATE KEY UPDATE. this change your two statements in to one.

Related

Is JpaRepository.save() suitable for entities with auto generated IDs if we want to UPSERT them?

I'm facing a problem with duplicate records in a MySQL database when I'm upserting using JpaRepository.saveAll() entities which are already present in the database. I want new entities to be inserted, existing ones to be updated(if there are changes to any of the properties), otherwise no action is expected.
The entity classes id property is annotated with #GeneratedValue(GenerationType.IDENTITY) and the id column in the corresponding table in MySQL has auto-increment enabled. I'm pointing that out because JpaRepository.save(), which is invoked for each entity in saveAll(), does a check by id if the entity is already present in the database.
Here is where in my opinion the contradiction between save(), when used for updating, and auto-generation of IDs occurs: You can't update existing records because all of the entities passed into saveAll() will have newly generated IDs and thus the check in save() will always say that they are not present in the database.
Is my logic correct?
The only solution to the problem that I can think of is to create a custom query that compares the records in the database with the newly passed entities by the values of another column whose values are unique. I can't compare them by id because I will encounter the same problem as in save().
Is that good enough and are there any other solutions?
Depending how you look at it, your are either wrong or right.
What you describe in terms of behaviour is correct: If you pass in an entity with id set to null to save you will always create a new row in the database and never perform an update. In that sense you are correct. That behaviour is independent of how the id gets generated for new entities.
But the id of an entity defines its identity. If two entities have the same id they represent the same row in the database thus the same logical entity and the behaviour of save is exactly that of an upsert. This is also independent of how the id gets generated for new entities.
If you want an upsert based on a different column (or columns) you need to write custom code, for example using an actual upsert statement in a query annotation. Alternatively you can try to load the entity by the columns in question and if you succeed set its values as desired and otherwise create a new entity and save that.

MySQL Id columns

I am working on a project that is an upgrade of an existing system.
The existing DB structure must be kept intact as there is a system reading the same DB that will be used ontop of the new system.
I am building a new CMS / Management system using a PHP framework that expects so see all DB table autoincrement ID field named simply "id" - I do not want to modify the PHP deal with anything other that "id" as this field name - trust me it will be a massive task.
The existing DB has non standard Autoincrement ID field naming, eg:
"iBmsId" -shcema: i=INT Bms = the name of the table, Id = ID....
Is there anything I can do to the DB itself to make a duplicate of the "iBmsId" column, to create a matched column called simply "id" that has the corresponding INT values? This way my new system will function as expected without having to do a serious re-write, and at the same time still have the existing system able to communicate with the DB?
In this situation you can just use VIEW :)
http://dev.mysql.com/doc/refman/5.0/en/create-view.html
View in dbms is like a virtual table (unless it's materialized). Views add a new abstraction layer which can support independency between how you use db and how it's implemented. It can also increase security for example by hiding some fields or making view readonly.
Notice: In order to add view transparently you can rename origin table and create the View with origin table name. This let's you avoid modifications in existing code.
You can read here how to create updatable and insertable view (which can behave as normal table).
If only one system at a time is modifying the value, then you can use a view:
create view v_table as
select t.*, iBMid as id
from table t;
Presumably, an auto-incremented value is not going to be updated, so this should be safe. However, keep in mind that:
To be more specific, a view is not updatable if it contains any of the following:
. . .
Multiple references to any column of a base table.
This could affect other columns that you might want to treat the same way.

Prevent Duplicate Table entry in Database

I'm trying to Create new table for record of each company and its information. And for that I'm using simple Create query. Is there any way to prevent duplication of Table?
In every database that I know of, duplicate table names are not allowed. In some, there is a third element, the schema, but I assume everything is in the same schema.
In other words, trying to create a duplicate will cause an error. Try it.
By the way, you should always tag your questions with the database you are using.

Inserting a column in SQL Server at a position in a table

Hello I need to add a column to a table in SQL Server 2008. If I use the script below:
ALTER TABLE SampleTable ADD SampleColumn bigint NULL
it adds the column at the end of the table. What if I want the column at a position in the table using script only. For some reasons which are hard to explain, I cannot drop table and execute a new create table script.
Any ideas and suggestions!
Column order is irrelevant.
Observe:
SELECT Col1, Col2, Col3
FROM Table
SELECT Col3, Col2, Col1
FROM Table
Column order only matters if you use SELECT * which is another reason not to do that.
Besides recreating the table, there is no way to change the default column order in the metadata.
If you need a workaround, it's possible to create a VIEW that selects the fields in the desired order and use that.
If you can use SSMS, then it's easy -- just "design" your table (r-click the table), add your column, then drag it up/down in the list wherever you want it.
That said -- if you view the change script for doing this (i.e., all of the TSQL behind that simple drag & drop), there is an awful lot that actually goes on automagically (including re-creating of the table).
I know column order DOES matter (sorry #JNK) for someone who likes to follow a standard organizational method (like having all of your foriegn keys toward the top, etc.), or someone supporting queries/procedures that don't specify columns (like you can do with insert statements, or selects based on position).
There isn't another way to insert a column in a SQL Server table "in between" existing columns - you need to build a temp table and rebuild the old table. That said, column order shouldn't matter - are you sure that the column needs to be inserted in order?
Likely your best bet is to just use the GUI, script it out, and then change the constraint name to something reasonable within the script. You're right that the numerical constraint name isn't ideal, and it's not a best practice to allow SQL Server to determine your object names.
check the below link for more:
stackoverflow.com/questions/965927/inserting-column-between-other-columns-in-sql-server-using-script

MySQL enum column from anothertable column

I'm sure this is either totally impossible or really easy:
If I'm creating a table and I want one of the columns to have limited options, it seems that I use either the ENUM or SET value type. But I have to define the possible values at that moment. What if I have another table which has two columns, a primary key column and a data column, and I want the ENUM for my new table to be set to the primary key of the already existing column?
I'm sure I can just write in the values long-hand, but ideally what I need is for new values to be entered into the list table and for the table with the enum column to just accept that the value choices will include anything new added to that list table.
Is this possible without needing to manipulate the structure of the new table each time something is added to the list?
i think this link help :
http://dev.mysql.com/doc/refman/5.0/en/enum.html
have a discussion of it
in the user comments
start :
"In MySQL 5.0, you can convert an enum's values into a dynamically-defined table of values, which then provides effectively a language-neutral method to handle this kind of conversion (rather than relying on PHP, Tcl, C, C++, Java, etc. specific code).
"
he do it with stored PROCEDURE
The easiest way is to use a regular column without contraints. If you're interested in all the current values, use DISTINCT to query them:
select distinct YourColumn from YourTable
That way, you don't have any maintenance and can store whatever you like in the table.
The foreign key table you mention is also a good option. The foreign key will limit the original column. Before you do the actual insert, you run a query to expand the "enum" table:
insert into EnumTable (name)
select 'NewEnumValue'
where not exists (select * from EnumTable where name = 'NewEnumValue')
Not sure what exactly you're trying to achieve btw; limit the column, but automatically expand the choices when someone breaks the limit?