Hibernate auto generate second id - java

Suppose that I have a table with only two columns ID and Car, and the Car column can have repeated values, for example:
id | car
1 | 200
2 | 200
3 | 201
4 | 201
5 | 201
6 | 202
I need a new column which automatically generates a second id grouped by Cars when new records are inserted, something that looks like this:
id | car | second_id
1 | 200 | 1
2 | 200 | 2
3 | 201 | 1
4 | 201 | 2
5 | 201 | 3
6 | 202 | 1
I've tried something like this but does not work:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(name = "car")
private int car;
#GeneratedValue(generator="second_id")
#GenericGenerator(name="second_id", strategy="com.example.SecondIdGenerator")
#Column(name = "second_id", unique = false, nullable = false, length = 20)
private int secondId;
SecondIdGenerator class for now only returns a fixed value for test, but this value is not showing in the db, in other words, it is not working.
How i do this?
Hibernate has something for this?
(I'm using MySQL db)

I am unaware of any tool support for this sort of column.
You can implement calculation of the value for the second_id column with a trigger. You would probably want a "before insert" trigger. The trigger would find the existing maximum second_id for the car that is being inserted and add one for the new row's second_id value. If you allow updates to the car column, you could support recalculation of the second_id column in the same way (although this would leave holes in the second_id sequence for the prior car value's second_id column).
You might find it easier to create a stored procedure that encapsulates the business logic if you are going to have multiple triggers that maintain the column value.
You would also want to have a unique constraint on (car, second_id). If you don't do this, you will get duplicates whenever you have multiple clients insert rows with the same car value. The unique constraint will only allow the first to commit to finish successfully. All other concurrent transactions that tried to insert a row with the same car value (and computed the same second_id value) will fail. Obviously, you need to handle this exception in the client by cleaning up and retrying the transaction.

at run time if there is no #Id specified hibernate will get an exception , i think you can change the structure of your table.

Related

Updating table in Schema 1 based on values of few columns of a table in Schema 2

I will try to explain the problem with the best of my ability.
SO I have 2 tables in 2 different Schemas with few columns in both & I own only 1 of the schemas.
What I need to do is Update Table A in Schema 1 with a value from one of the fields from Table B from Schema 2.
I need to update only few rows in this table
The problem lies in when table A is populated the data in Table B is not ready with the data.
I am trying to this programmatically if possible.
Since, they are in different schemas & update size is comparatively smaller than the A's table size what should be the best way to do this?
SAMPLE DATA
**
Table A
orderNum | orderNumInternal | validity | averageSales |type
1000 | 5636 | 2020-06-30 00:00:00.000 | NULL |valid
Table B
orderNum | orderNumInternal | validity | averageSales
1000 | 5636 | 2020-06-30 00:00:00.000 | 65
**
Here I need to update Table A with the averageSales value from Tabel B whenever the type in Table A is valid & there is match in table B for the first 3 columns
Table A is created in an overnight whilst I don't have control over when the data would be available in Table B
Would this not simply be an UPDATE with a JOIN?
UPDATE A
SET averageSales = B.averageSales
FROM Schema1.TableA A
JOIN Schema2.TableB B ON A.orderNum = B.orderNum
WHERE A.averageSales IS NULL; --Unsure if this WHERE is needed

Spring Data with strict In-clause

See updated question below
I want to query for elements where every element is required to have all given attributes of e.g. a set to be returned, not only one.
Default Spring Data Jpa Query, where one attribute is enough:
findAllByAttributeIn(Set<Attribute> setAttr)
Example problem
For these elements (abstracted, no actual table)
id | attr
----------
1 | A
2 | A,B
3 | A,B,C
with this filter:
setAttr: [A,B]
the default query
findAllByAttributeIn(Set<Attribute> setAttr)
returns all elements (by ids):
[1,2,3]
Desired result is only the second element (with [A,B]).
Is that possible with the given Spring Data Jpa query keywords or is the only solution to create a custom query?
Updated question:
There are two entities, Media and Tag. They have a many-to-many relationship which is realised in the table Media_has_tags. Every media can have any number of tags (0..*). So in my Spring app, media has a set of tags as an attribute and vice versa. The classes:
Media = {
id: string,
Set<Tag> tags,
...
}
Tag = {
id: string,
Set<Media> medias,
...
}
The corresponding tables are:
Media
-------
id | ...
Tag
-------
id | ...
title | ...
Media_has_tags
-------
media_id | tag_id
And now I have a set of tags with which I want to get all medias which have every tag of that set. They can have more tags of course, but they need to have every tag of the set I am providing.
Concrete example:
Media
-------
id | ...
-------
1 |
2 |
Tag
-------
id | title | ...
1 | A |
2 | B |
Media_has_tags
-------
media_id | tag_id
1 | 1
2 | 1
2 | 2
Given a set of tags [A, B] I want only media with id 2 as a result since media with id 1 doesn't have tag 'B'.
Can I achieve that with Keywords and if, how or do I have to build my own query?
Sorry, but your question is incorrect initially.
findAllByAttributeIn(Set<Attribute> setAttr)
produces an SQL request like this:
select * from <table_name> t where t.attribute in (?,?,?...?)
So according to RDBMS-rules your result is correct and expectable.
What is a real structure for your abstract tables?
id | attr
----------
1 | A
2 | A,B
3 | A,B,C
In real life it would be somethink like this:
id | attr
----------
1 | A
2 | A
2 | B
3 | A
3 | B
3 | C
And again - in this case the result you have got is ok for any RDBMS.
Give us real examples from your project, please
Update because of question update:
OK, the problem has been clarified.
In this case there is no straight way to solve it using standard CrudRepository syntax. But you can try to write #Query request to manage to get the goal.
In a clear SQL this problem has to be solved by using group by together with having. It would be something like this:
select media_id
From media_has_tags
Where tag_id in(1,2 3)
Group by media_id
Having count(*)=3
In terms of SpringData it means that you have to create MediaHasTagsRepository interface and an appropriate query method to get looked ids. After that you can easily find medias you're looking for.
But this approach is not looking good IMHO. The best way I suppose is to find all the medias by the your initial query and than filter them by the given condition in Java.
E.g. you have a List<Media> where each element has an least a one tag that you are looking for. Then we can do a loop to find medias that contains all the looked tags:
List<Media> list; // here is a filled list of medias
Set<String> titles; // here is a set of title interseptions we a looking for
final List<Media> result = new ArrayList<>();
for (Media media: list) {
if (!list.getTags().isEmpty()){
Set<String> tagTitles = list.getTags().stream().map(item -> item.getTitle()).filter(title -> titles.contains(title)).distinct().collect(Collectors.toSet());
if (tagTitles.size() == titles.size()) {
result.add(media);
}
}
}

How to add a new value to a field which will depend of two other fields of the same registry?

I have 3 columns:
grossWeight | tare | netWeight
the value of the first two fields will decide the value of the third field:
grossWeight | tare | netWeight
50 40 ?
i want the follow... grossWeight - tare = netWeight
grossWeight | tare | netWeight
50 40 10
how can i reach that with SQL ?
You cqn do it with something like:
update yourTable set netWeight = grossWeight - tare;
Consider to use triggers for more flexibility: when using a trigger you can configure it to be automatically excuted when grossWeight and/or tare are inserted or updated.

How to process columns of an SQLite table in Java android?

I have an SQLite table like:
+---+-------------+----------------+
|_id| lap_time_ms |formatted_elapse|
+---+-------------+----------------+
| 1 | 5600 | 00:05.6 |
| 2 | 4612 | 00:04.6 |
| 3 | 4123 | 00:04.1 |
| 4 | 15033 | 00:15.0 |
| 5 | 4523 | 00:04.5 |
| 6 | 6246 | 00:06.2 |
Where lap_time_ms is an of the type long and represents the amount of time in milliseconds for a lap while formatter_elapse is a String that represents the formatted (displayable) form of the first column (elapse).
My question is that if I want to add (say) 5 seconds (5000) to each lap_time_ms then I use a statement like:
DB.execSQL("update table_name set KEY_ELAPSE=KEY_ELAPSE+5000);
Which works fine however the problem is that formatted_elapse still retains its outdated value!
So, what is the best way to update the values in the formatted_elapse column if I have a function like:
public static String getFormattedTime(long milliseconds) {
// custom code that processes the long
return processedString;
}
It may be a long shot (metaphorically speaking of course ;) but is it possible to have SQLite link the two columns such that if I update a lap_time_ms row, the formatted_elapse will automatically update appropriately.
Thanks in advance!
In theory, it would be possible to create a trigger to update that column, but only if the formatting can be done with some built-in SQLite function (Android does not allow user-defined functions):
CREATE TRIGGER update_formatted_elapse
AFTER UPDATE OF lap_time_ms ON MyTable
FOR EACH ROW
BEGIN
UPDATE MyTable
SET formatted_elapse = strftime('%M:%f', NEW.lap_time_ms, 'unixepoch')
WHERE _id = NEW._id;
END;
However, it would be bad design to store the formatted string in the database; it would be duplicated information that is in danger of becoming inconsistent.
Drop the formatted_elapse column and just call getFormattedTime in your code whenever you need it.

Oracle column name issue

I have parent-child mapping in hibernate where the entities are connected through table.
The problem is that column automatically created by hibernate in this table is called like "_actions_id". But I use Oracle and it says that column name "_actions_id" is invalid.
It works fine when I wrap the name with "" and execute the script manually, but is there a way to make hibernate to wrap all columns with "" ?
In your example, you specified a join table, which is for scenarios like this
People table:
PID | Name
1 | Albert
2 | Bob
TelephoneNumbers table:
TID | Tel
1 | 123-456
2 | 456-789
3 | 789-012
Join table:
PID | TID
1 | 1
1 | 2
2 | 3
I.e. the column that connects the current entity to the entity in the collection is in neither the current table nor the table for the collection entity. This is more useful for the many-to-many mapping, but you can also use it for OneToMany if you don't have control over the TelephoneNumbers table for example. Otherwise you should just use plain #JoinColumn.
The usage of #JoinTable has been explained many times by many websites. See the JavaDoc and this question.
I think you want a custom NamingStrategy. I got the idea here. In your case, it would be something like:
public class MyNamingStrategy extends DefaultNamingStrategy {
public String logicalCollectionColumnName(String columnName, String propertyName, String referencedColumn) {
return "`" + super.logicalCollectionColumnName(columnName, propertyName, referencedColumn + "`";
}
}

Categories