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.
I'm building an app in which users can create entities that are stored in my Entity table with some caracteristics like "space_below" and "width". Users can also create their own groups of entities by choosing amongst everybody's entities. Once they picked someone else's entity, I want them to be able to modify some caracteristics like the "width" and save these modifications for their own group. What would be to best way to do that in my DB?
First approach
Each time a user do a modification, create a new record (almost a duplicate) in the Entity table and then only refer to this new entity from the group where it was change.
In this case, I would need to add a column to my Entity table to differentiate original entites from copied entites.
Second approach
In any scenario, I will have a junction table between the Group table and the Entity table. In this junction table, I could add a "modification" column in which I store a JSON with the modifications. Something like { space_below: '8', width: '200' }. If there is no modficiation, the value of the column will be null.
I think I prefer the second approach since the first one involves a lot of duplicated data in the Entity table, but might not be aware of other implications.
I have not used access for many years, but need what I thought was a simple DB and struggling at early stage.
I have a table that represents objects that can belong to multiple systems and may have some different attributes between the systems.
So my initial idea was to have a table for Systems, a table for Objects, and a child table for Object Attributes.
My Objects table currently is 3 fields:
Key : Autogenerated
Object Name : Text
System : Lookup to system table
Object Name will not be unique as it can appear in multiple systems, so I want to create a unique compound key of the Object Name & System field. This key will be what joins this table to the child Object Attributes table.
My problem is that the System lookup field does not appear in the available fields to use when trying to create a compound key.
Could someone tell me where I am going wrong?
This might not even be possible to do. I have one table that contains items. (item_id, item_name, description, json for deserializing into an actual object)
My second table contains packages. (package_id,package_name,price,description,item_list(2D array))
The 2D array needs to match item_id values to quantities.
Normally, I would simply serialize a JSON array to the item list spot. I worry about item_id values being removed or changed though. I cannot use a foreign key to have a change "cascade" or "delete" child values. Is there a way to store a kind of sub-table in a mysql row?
Let me know if my problem description is not clear. I want to make sure it is followable for anyone else who is trying to find an answer. I might include some images later if it will help.
Solution: No, there isn't a way to store a 2D array in a MySQL row. You have to use a bridge table. Oh well, at least there is a solution. A solution always exists.
Well you can always store 2D array in a column of a database but there is a problem with it, i.e retrieving data from mysql you'll have to parse that column and that column of yours will contain multiple values. When you have a multivalued attribute in your table it must be migrated to another table to normalize your database design.
In your case you are looking at many-to-many relation ship i.e a package may have many items and an item may be taken by many packages. To solve many-to-many relation you have to introduce a new table usually called a Bridge table. that bridge table will take Primary Keys from both item and package tables as Foreign Keys. The reason you add this table is to remove redundancy and that is one of many things normalization is offering.
What you are looking for is called a many-to-many relationship. Usually you create an extra table that creates a map between the two tables. Here is one example:
Many-to-many relationships examples
I was able to store a 2D array as a JSON object by using the index of the second dimension as a key. Here's an example of a 12 x 4 array:
{"0": "[0,0,0,0,0,0,0,0,0,0]", "1": "[0,0,0,0,0,0,0,0,0,0]", "2": "[0,0,0,1,0,1,0,1,0,0]", "3": "[0,0,0,1,1,1,1,1,0,0]"}
Database tables:
Tutor( {PK}tutorId, name )
Module( {PK}moduleId, name, {FK}tutorId )
Relationship Tutor -> Module (OneToMany)
Questions:
If you create the domain model
classes with JPA annotations, the
corresponding database tables are
auto-created with the same columns as the annotated fields of the class?
Do you create the database first
and then the JPA classes with the
same fields as the database table
columns?
How do you model foreign key constraints with JPA
(1) and (2) are depended on your situation. you can create domain model class first and it will generate table and columns which are the similar to the fields. In addition, you can establish a database first (it is easy to design and have better view of the whole database.), then map the tables to your domain class.
about (3) you can try this link