Join multiple secondary tables - java

I have following tables:
master_table(id, col1, col2, discriminator_col)
join_table1(m_id, v_id)
value_table1(id, val)
join_table2(m_id, v_id)
value_table2(id, val)
there is single master table and several value tables joined to master table via join tables. Value tables contain single scalar value for each master_table row. Values from separate values tables are placed into descendant entities, so there are one MasterEntity and several Child1Entity, Child2Entity etc.
I would like not to create a separate entity for each value_table, just for each ChildEntity and somehow join value table to that entity.
MasterEntity:
#Entity
#Inheritance(...) // not sure what type of inheritance to use
public class MasterEntity {
#Id
private int id;
private String col1;
private String col2;
}
Child1Entity:
#Entity
public class Child1Entity extends MasterEntity {
// need to get value_table1.val column here
}
I could create entity for value_table and add many-to-one relation to Child1Entity, but if it is possible to avoid I would like to do that.
I tried to add two secondary tables (join_table1, value_table1) to Child1Entity, but I can not join join_table1 with value_table1, just with master_table.

If you want to use #Inheritance, you can't have those join_tables. With those join tables, your model says:
one value can belong to multiple master rows
one master row can belong to multiple value rows
If you just want: 1 master belongs to 1 value row, than use this:
master (id, ...)
value1 (masterId, ...)
value2 (masterId, ...)
With #Inheritance(strategy=InheritanceType.JOINED).
For more information have a look here: http://en.wikibooks.org/wiki/Java_Persistence/Inheritance
BUT: Whenever you use #Inheritance you will have to create a separate #Entity class for everything.
If you really need the 5 table layout from above, use #ManyToMany.
Basically JPA is made for Mapping Java Objects to SQL Tables, not the other way round ;) If you need to do thing's which aren't possible using JPA (or too complicated), you can always use JDBC and craft your queries and Entity mappings by hand.

Related

Is there a way to select all columns for a SELECT statement with JOINs without breaking the entity mapping?

I have a application_user table with a corresponding UserEntity record. Additionally, I have a user_meta_data table with a UserMetaDataEntity record as a 1:1 relation to the user.
#Table("application_user")
record UserEntity(#Id #Nullable Long id,
// more columns
#Nullable
UserMetaDataEntity metaData
) {
// (...)
}
Currently, I need to directly write SQL queries, as I have some complex queries at hand that can't be modeled easily via function names. In these queries, I need to explicitly select all columns
#Query("""
SELECT application_user.ID AS ID, user_meta_data.phoneNumber AS USERMETADATA_PHONE_NUMBER
FROM application_user
INNER JOIN user_meta_data ON user_meta_data.user_id = application_user.id
""")
Stream<UserEntity> streamUsersWithMetaData();
But I want to avoid explicitly defining column names, as my actual entities have many columns. I would prefer calling SELECT * FROM application_user INNER JOIN ... but this doesn't work, as Spring Data JDBC expects the column names to be prefixed with the joined table name.
Is there a way to define custom SQL queries without needing to define all columns in the SELECT statement?
You can't use SELECT * but there are at least two ways you can minimise the pain.
Either you define a static final String containing the list of columns and concatenate them with the rest of the query.
Alternatively you can specify a RowMapper doing the mapping. It could wrap the ResultSet and forward the call to the original EntityRowMapper

Hibernate : Map single VO to two tables

I have two tables - Table1 and Table2. Data structure of both the tables is same.
I have single VO for both Table1 and Table2. I have two .hbm.xml file for two tables separately -
Table1.hbm.xml and Table2.hbm.xml
In my java code, based on a condition I either need to save to Table1 or Table2
if(someCondition)
{
session.saveOrUpdate(VO); //This should be for Table1
}
else
{
session.saveOrUpdate(VO); //This should be for Table2
}
My problem is since that VO is same, there will be conflict in deciding which table to save.
Is it possible to have same VO mapped to two tables?
Note: The reason why I have such a requirement is Table1 and Table2 are in separate tablespace. One is partitioned and the other is not.
There are couple of other reasons for such a weird requirement which is beyond my control to change the architecture now.
In my opinion using two entity managers is a bit too much. What you need is to have a good abstraction around the table.
You can map the same class as many times you want you just have to map it under different name.
Than one good Repository pattern working with the abstract entity (instead of the concrete one) combined with a Factory or Builder to generate the two objects will get the job done. If you follow this approach you will not need to have this IF-ELSE flow.
#MappedSuperClass
class AbstractMappedSomeTimes {
private mappedAttribute;
}
#Table("yourtablename")
public class MappedOnce extends AbstractEntity{
}
#Table("yourtablename")
public class MappedTwise extends AbstractEntity{
}
Than you can have Repository working with AbstractMappedSomeTimes types of objects. You can also create a Factory that will generate either MappedOnce objects or MappedTwise objects.

Converting an entity to an enum and vice versa in JPA

Scenario:Let us assume a unidirectional relationship A->ManyToOne->B ( hence 2 tables A and B) in JPA. Typically, this will be mapped in Entity A as:
#ManyToOne
#JoinColumn
B b;
Table A will hence contain a foreign key which will be primary key in Table B.
Further, let us assume that B is a table that contains static values.
In JPA the * -> One mappings are eager by default. To avoid an extra query, I can always do a join fetch to avoid the extra query.
I understand how enums can be used/converted to store a column value in a table.
Questions:
Would it really be a value addition to have an enum representation
for the static values when we already have a table and hence an
entity for table B?
If we do have an enum,is it possible to convert the entity B to an
enum (representing static values) and vice versa? I have usually
seen enum converted into a column in table and not a complete
entity/row in a table.
Even if the above works and we want to retrieve A and B, can the
enum be used to avoid the extra join (without the fetch join) while
doing the conversion?

POJO data with one to many / many to one relationship(JDBC)

For example I have two entities : Enterprise, Department. Enterprise has many departments, department has one enterprise, so there is a column - Enterprise_ID in Department table.
I have a function for saving Department object
void save(Department department);
To add Enterprise_ID in the table I need to have either reference on Enterprise object or enterprise's id.
Which way is more suitable?
However I prefer do not have such information in department object but on this way how can I save Enterprise_ID in the table ? It seems to me Hibernate somehow doing it.
public class Department{
private long id;
private String name;
private DepartmentType type;
private List<Employee> employees;
//getters()/setters()
}
public class Enterprise{
...
private List<Department> departments;
...
}
Department does not have any information about Enterprise in which it exists. So using only department object I can't insert Enterprise_ID(FK) in department table. But hibernate's save method somehow doing it. How can I do it without hibernate using entities above;
I use JDBC.
To do it the same way as hibernate does, you would have a save(Enterprise) method that would persist the enterprise object to the db and also insert/update the foreign key association.
Hibernate supports both nullable and non-nullable foreign key. In the latter case, it will first insert the enterprise, obtaining its primary key value, and then insert the department's along with the correct foreign key value.
You could do the same. But the save(Department) method would only be able to do updates on the department table and not change the association to the enterprise table. To do that, you would have to change the collection in enterprise and save/update that to the db.
Hibernate will only save/update the foreign key if you change something in the Enterprise.departments collection. It's the only way to do it if you don't have the reverse relation.
In your code, you'll have to use the Enterprise object to update the foreign keys in the Department table.
You could create a bidirectional association, by putting a field 'enterprise' in your Department class, but then you need to keep both relations in synch manually...

How to map class to multiple tables which are not related in hibernate?

I've a class which has a lot of attributes(for e.g 25). Let's say we have 5 groups each having 5 attributes as an arrangement. Each of these groups refers to a different table which has no relation whatsoever to the other tables for the other groups. Is it possible to do such a mapping in Hibernate?
class Test
{
string var1;
string var2;
string var3;
string var4;
string var5;
}
Table1:
Column:var1
Table2:
Column:var2
Table3:
Column:var3
Table4:
Column:var4
Table5:
Column:var5
Now I need to have a hibernate mapping (.hbm) file in which I need to map class test with table1,table2,table3,table4,table5. Is this possible to do?
It's impossible. Impossible get values from differrent tables, without relationships. You can map one table on one entity or one entity on many tables using JOIN strategy. But you cann't using JOIN without relationship. So this is impossible

Categories