Hibernate bit array to entity mapping - java

I am trying to map a normalized Java model to a legacy database schema using Hibernate 3.5. One particular table encodes a foreign keys in a one-to-many relationship as a bit array column.
Consider tables person and club that describes people's affiliations to clubs:
person: .----.------. club: .----.---------.---------------------------.
| id | name | | id | name | members | binary(members) |
|----+------| |----+---------|---------+-----------------|
| 1 | Bob | | 10 | Cricket | 0 | 000 |
| 2 | Joe | | 11 | Tennis | 5 | 101 |
| 3 | Sue | | 12 | Cooking | 7 | 111 |
'----'------' | 13 | Golf | 3 | 100 |
'----'---------'---------'-----------------'
So hopefully it is clear that person.id is used as the bit index in the bit array club.members:
.---.---.---.
| S | J | B |
| u | o | o |
| e | e | b |
|---+---+---|
| 1 | 0 | 1 |
'---'---'---'
In this example the members column tells us that:
no one is a member of Cricket --- no flags set
Bob/Sue -> Tennis --- flags at positions 1 and 3 are set
Bob/Sue/Joe -> Cooking --- flags at positions 1, 2 and 3 are set
Sue -> Golf --- flag at position 3 is set
Now, for this example a join table could've been used instead which would simplify matters and avoid many potential issues - e.g: the maximum range of members placing an upper bound on the number of people rows. However, I am stuck with this schema and it seems that there were factors in favour of using a bit array column way back when.
In my Java domain I'd like to model this schema with entities like so:
class Person {
private int id;
private String name;
...
}
class Club {
private Set<Person> members;
private int id;
private String name;
...
}
I am assuming that I must use a UserType implementation but have been unable to find any examples where the items described by the user type are references to entities - not literal field values - or composites thereof. Additionally I am aware that I'll have to consider how the person entities are fetched when a club instance is loaded.
Can anyone tell me how I can tame this legacy schema with Hibernate?
Update
I have recently had to revisit this type of mapping in a legacy database. This time around it became apparent that our equivalent of the members table was actually a static set and could be hardcoded as an Enum. With this simplification it was fairly straightforward to implement a Hibernate UserType that converted between the bit array and a set of enums.

I've never faced this situation but I think that you'll need to implement a custom UserCollectionType (see chapter 5.2.3. Custom value types in Hibernate Core documentation), the UserCollectionType being an extension point which may be used to support any damn collection and collection semantics you like.
I'm not sure how well they are supported by annotations though (according to HHH-4417, you may have to use a hack). Using hbm.xml for this would be a good idea here IMO.
Some more pointers/discussions:
https://forum.hibernate.org/viewtopic.php?f=9&t=938522&start=0
http://www.javalobby.org/java/forums/m91832311.html (different case but may give you an idea of how to start)

Related

Visualise data loaded in memory from databases/tables for doc purposes

I have a set of classes that do load data from some tables from multiple databases and keep the data in memory in specific data structures (Maps etc).
What I want to do is create some visual/documentation of how each structure is loaded by which db/table.
Is there something other than e.g. google doc or Word doc to use for this? Would it be some form of UML diagram or is it some other kind of diagram I should be looking into?
E.g.
HashMap<Integer, Person> is loaded from emp.Employees and personal.People etc
A very typical way to document this it to use UML stereotypes to identify classes that represent database objects (tables, views, ...), and show dependency between the "in-memory" classes and the database objects.
Example:
+------------+ +--------------+
| Person | | <<table>> |
+------------+ <<load>> | Employees |
| ... | - - - - - - - > +--------------+
+------------+ \ | ... |
| ... | +--------------+
+------------+ \
+------------+
\-> | <<table>> |
| People |
+------------+
| ... |
+------------+
You could then show that Person is in a container. Typically in UML you could show this either with a simple association with a container class or, in the case of the hashmap, with a qualifier.
You may also want to use the full name of your tables, or use package notation to group tables in the same schema.
Additional example: visual mapping of classes and tables using <<table>>; use-dependencies to show load/saving relationships

Write Spring Specification to filter unrelated tables

I am working on a project Spring and Java, generated using JHipster. I want to filter on table that doesn't have a direct relationship with another.
My purpose is almost asked in a previous similar question
Write Spring Specification with multiple inner join & other conditions
But in my case , I ve two unrelated entities :
Consultant (id : Long , FullName : string , profileRank : Enum of string )
Rank (id : Long , level : Enum of string , rate : Double )
Consultant | Rank
|
id | FullName | profileRank | id | level | rate
1 | aaaaa | 'ONE' | 1 | 'ONE' | 1
2 | bbbbbb | 'THREE' | 2 | 'TWO' | 2
3 | cccccc | 'FOUR' | 3 | 'THREE' | 3
4 | dddddd | 'THREE' | 4 | 'FOUR' | 4
I want to filter consultant list by rate using level
Example : get consultants with rate greater than 3
Expected result
id | FullName | profileRank
3 | cccccc | 'FOUR'
I ve searched in documentation and many articles without get it to work please how to achieve that .
You don't need to write a specification for your case.
Fetch all the ranks with levels and rates
Filter these values and keep only the ones greater than 3 (step 1 and 2 can be combined). The result will be a List<Rank> that contains only FOUR rank
list.stream(rank => rank.level).collect(toList())
The result of step 3 will be passed to a repository method like List<Consultant> findByProfileRankIn(List<String> levelNames)
Another alternative would be joins something like this Joining tables without relation using JPA criteria
If you still want a spec that's also possible. Spring Data Join with Specifications

How to ensure that there are no race conditions in a database update statement using spring

Imagine there are two entities Children and Gifts. Let's say there are 1000 children and 10 gifts. Children will always try to grab available gifts, and gifts will be tagged to children on a "first come, first serve" basis.
Table structure
children table
+----+------+
| id | name |
+----+------+
| 1 | Sam |
| 2 | John |
| 3 | Sara |
+----+------+
gift table
+----+---------+-------------+
| id | gift | children_id |
+----+---------+-------------+
| 1 | Toy Car | 2 |
| 2 | Doll | 3 |
+----+---------+-------------+
Here the children_id is the child who grabbed the gift first.
In my application, I want to update the children_id in such a way that only the first child who initiated the request will get it and rest get a GiftUnavailableException.
How will I ensure that, even if a 1000 requests come at a time to grab a specific gift, only the first one will get it. Or how will I ensure that there are no race conditions for this update.
Are there any spring specific feature that I can make use of or are there any other ways.
I'm using spring-boot as my backend.
I can't post a comment so here I go !
I assume you are using Spring Data JPA.
Then you should use #Transactional annotation : This mean that everytime you are requesting your database, you do a transaction :
Begin Transaction
Execute Transaction
Commit Transaction
Lot of usefull informations about this (Read it !!): Spring #Transactional - isolation, propagation
You will need to seed your Transactional Isolation to Serializable and maybe change the propagation method.
And if you are not using Spring data JPA.. Well There is a synchronized keywords but I think it's a bit awful to use it here.

Obtaining the primary key from an inserted DataSet to chain into other insertions

Suppose I have the following tables, in an Oracle DB
Foo:
+--------+---------+---------+
| id_foo | string1 | string2 |
+--------+---------+---------+
| 1 | foo | bar |
| 2 | baz | bat |
+--------+---------+---------+
Bar:
+--------+-----------+--------+
| id_bar | id_foo_fk | string |
+--------+-----------+--------+
| 1 | 1 | boo |
| 2 | 1 | bum |
+--------+-----------+--------+
When I insert into Foo, by using a Dataset and JDBC, such as
Dataset<Row> fooDataset = //Dataset is initialized
fooDataset.write().mode(SaveMode.Append).jdbc(url, table, properties)
an ID is auto-generated by the database. Now when I need to save Bar, using the same strategy, I want to be able to link it to Foo, via id_foo_fk.
I looked into some possibilities, such as using monotonically_increasing_id() as suggested in this question, but it won't solve the issue, as I need the ID generated by the database. I tried what was suggested in this question, but it leads to the same issue, of unique non-database IDs
It's also not possible to select from the JDBC again, as string1 and string2 may not be unique. Nor is it possible to change the database. For instance, I can't change it to be UUID, and I can't add a trigger for it. It's a legacy database that we can only use
How can I achieve this? Is this possible with Apache Spark?
I'm not a Java specialist so you will have to look into the database layer on how to proceed exactly but there are 3 ways you can do this:
You can create a store procedure if the database server you are using is capable of (most do) and call it from your code.
Create a trigger that returns the id number on the first insertion and use it in your next DB insertion.
Use UUID and use this as the key instead of the database auto generated key.

Suggest framework for external rule storage

There is a situation:
I've got 2 .xlsx files:
1. With bussines data
for example:
-----------------------------------------
| Column_A | Column_B| Column_C | Result |
-----------------------------------------
| test | 562.03 | test2 | |
------------------------------------------
2. With bussiness rules
for example:
-------------------------------------------------------------------------
| Column_A | Column_B | Column_C | Result |
-------------------------------------------------------------------------
| EQUALS:test | GREATER:100 | EQUALS:test2 & NOTEQUALS:test | A |
--------------------------------------------------------------------------
| EQUALS:test11 | GREATER:500 | EQUALS:test11 & NOTEQUALS:test | B |
--------------------------------------------------------------------------
With condition in each cell.
One row contains list of these conditions and composes one rule.
All rules will be processed iteratively. But of course, I think, it would be better to construct some 'decision tree' or 'classification flow-chart'.
So, my task is: to store these conditions functionality (methods like EQUALS, GREATER, NOTEQUALS) in some external file or some other resource. To have a possibility to change it without compilation into java bytecode. To have a dynamic solution, not to hard code in java methods.
I found DROOLS http://drools.jboss.org/ as a whay that can work with such cases. But maybe there are another frameworks that can work with such issues?
JavaScript, DynamicSQL, DB solution is not suitable.

Categories