How to "flatten" a data - java

I have a REST endpoint which takes a POJO and saves it.
#Service
public class CassandraService {
#Autowired MyReactiveCassandraRepository cassandraRepository;
public Mono<String> save(Pojo pojo) {
return cassandraRepository.save(pojo);
}
}
#Repository
public interface MyReactiveCassandraRepository extends ReactiveCrudRepository<Pojo, String> {
#Table
public class Pojo {
#PrimaryKey
private String id;
private String foo;
private InnerPojo innerPojo;
public class InnerPojo {
String aaa;
String bbb;
If you look at the data, you can see there are primitive types, but there is also an Object (InnerPojo in my example).
Instead of storing the data with "two levels", I would like to "flatten" the data, and save it that way:
| id | foo | aaa | bbb |
|----|-----|-----|-----|
| | | | |
| | | | |
| | | | |
Currently, I am duplicating a POJO entirely:
#Table
public class FlattenPojo {
#PrimaryKey
private String id;
private String foo;
private String aaa;
private String bbb;
And modify, create conversion code in my entire project to save this "duplicate" pojo in order to save the "flatten" version.
Is there a smarter way to save this the flatten formed in Spring Boot?

You can mark your innerPojo property as #Transient and have "flattened" private properties populated by InnerPojowhen calling the constructor. You have to re-create InnerPojo in #PostConstruct from those "flattened" properties then when loading.

Related

How to store collection of values as attributes in DynamoDB table?

I have a structure with collection of items inside that need to stored in DynamoDB table. Using current implementation items are stored as JSON but I would like to have them as unique attributes in table. Is it possible using spring-data-dynamodb library?
#Getter
#Setter
#DynamoDBTable(tableName = "orders")
public class Order {
#DynamoDBHashKey
#DynamoDBAutoGeneratedKey
private String id;
#DynamoDBAttribute
private long userId;
#DynamoDBAttribute
private List<Item> items;
}
#Getter
#Setter
#DynamoDBDocument
public class Item {
#DynamoDBAttribute
private String name;
#DynamoDBAttribute
private String value;
}
Expected result:
Table: orders
| id | userId | item_name1 | item_name2 | item_name3 |
| s2 | 234 | item_value1 | item_value1 | item_value3 |

Single table inheritance and relationship

I'm trying to find a solution for a this problem:
We have a table (code_list) in the database which contains all enum -like data.
Let us say we have an Affiliate that can have an AffiliateType and a LanguageCode.
We put all this in the code_list table where id_code_list field tells us if we are talking about AffiliateType or Languagecode and we can have a String or Integer identifier that tells us about which AffiliateType we are talking.
Example of the data in table:
| id_code_list | val_num | val_string | label |
| :----------: |:------: |:---------: | :-----:|
| TYP_AFF | 3 | 3 | Other |
| TYP_AFF | 1 | 1 | Divers |
| COD_LAN | 1 | 1 | French |
I tried to map this that way:
Code List Parent
#Entity
#Table(name = "CODE_LIST")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "ID_CODE_LIST")
public abstract class CodeListString {
#Id
#Column(name = "VAL_STRING")
protected String value;
#Embedded
protected Label label;
...
Affiliate Type:
#Entity
#DiscriminatorValue("TYP_AFF")
public class AffiliateType extends CodeListString{
public static final AffiliateType SOCIAL_SECRETARIAT = new AffiliateType("1");
public static final AffiliateType VARIOUS_SERVICES = new AffiliateType("2");
public static final AffiliateType OTHERS = new AffiliateType("3");
public static final AffiliateType SOPA = new AffiliateType("9");
public AffiliateType() {}
private AffiliateType(String value) {
super(value);
}
}
And my Affiliate entity:
#Entity
#Table(name = "AFF")
public class Affiliate {
#ManyToOne
#JoinColumn(name = "TYP_AFF")
private AffiliateType type;
But I'm getting this error:
org.hibernate.MappingException: Foreign key (FK7re97tvvbbo2km961gy9b5jw6:aff [typ_aff])) must have same number of columns as the referenced primary key (code_list [val_string,id_code_list])
So, is there a way to make this work or do you have other solution for this problem ?
PS: I'm using Hibernate and the solution like
#ManyToOne(targetEntity = AffiliateType.class)
#JoinColumn(name = "TYP_AFF")
#Where(clause = "ID_CODE_LIST='TYP_AFF'")
private AffiliateType type;
Doesn't work...
I've removed a dependency to a custom library and this worked.
I could not reproduce this error on a clean project.
Anyway this solution is really slow !

Is it possible to avoid persisting of subclass with JPA?

I know you can ignore fields with #Transient annotation. I cannot find the way to denote that I don't want specific subclass to be persisted in database. Here are model classes:
Element class:
#Entity
public class Element {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
Long id;
#OneToMany(cascade = CascadeType.ALL)
private Map<String, Base> map;
private String text;
}
Base class:
#Entity
#Inheritance(strategy= InheritanceType.JOINED)
public abstract class Base {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
Long id;
String type;
}
Foo class:
#Entity
public class Foo extends Base {
boolean flag;
}
Bar class:
#Entity
public class Bar extends Base {
int number;
}
Test object persisted:
Map<String, Base> map1 = new HashMap<>();
map1.put("foo-1" , new Foo());
map1.put("bar-1" , new Bar());
repo.save(new Element("element-1" , map1));
Table generated:
element table:
+------+-----------+
| id | text |
|------+-----------|
| 1 | element-1 |
+------+-----------+
element_map table;
+--------------+----------+-----------+
| element_id | map_id | map_key |
|--------------+----------+-----------|
| 1 | 1 | bar-1 |
| 1 | 2 | foo-1 |
+--------------+----------+-----------+
base table:
+------+--------+
| id | type |
|------+--------|
| 1 | <null> |
| 2 | <null> |
+------+--------+
foo table:
+--------+------+
| flag | id |
|--------+------|
| False | 2 |
+--------+------+
bar table:
+----------+------+
| number | id |
|----------+------|
| 0 | 1 |
+----------+------+
Is it possible to configure JPA to ignore Bar class and do NOT persist it in DB?
I tried adding #Transient annotation to all fields in Bar class but I end up with a bar table generated with only one field id inherited from the Base class. I would like to avoid having useless table database.
I tried removing #Entity annotation from Bar class but I end up with an exception each time a Bar object is persisted:
Caused by: org.springframework.orm.jpa.JpaSystemException: Unable to resolve entity name from Class [ch.smooth.hibernateinheritancehashmap.Bar] expected instance/subclass of [ch.smooth.hibernateinheritancehashmap.Base]; nested exception is org.hibernate.HibernateException: Unable to resolve entity name from Class [ch.smooth.hibernateinheritancehashmap.Bar] expected instance/subclass of [ch.smooth.hibernateinheritancehashmap.Base]
Any ideas how to specify part of class hierarchy to be transient?
I've isolated the problem for easier reproduction in a small spring-boot application on github: https://github.com/gladky/jpa-persistence-issue. Running mvn install will yield the exception which I mentioned.

How to use generic type parameter with Hibernate 5?

Below are the class definition
interface
public interface myInterface{
void myMethod1();
}
MyClass1 Class which implements above interface
#Entity
public class MyClass1 implements MyInterface{
#Id
private int id;
private String field1;
private String field2;
// Getter and setter
}
MyClass2 Class which implements above interface
#Entity
public class MyClass2 implements MyInterface{
#Id
private int id;
private String field3;
private String field4;
// Getter and setter
}
And finally the entity class which has a list with type parameter.
#Entity
public class MyClass{
#Id
priviate int id;
private String field5;
private String field6;
private List<? extends MyInterface> mylist;
//getter and setter
}
The generated class I'm looking at would look like something like below.
MyClass Table
-------------------------
id | field5 | field6
-------------------------
1 | abc | def
2 | abc | def
3 | abc | def
MyClass1 Table
-------------------------
id | field1 | field2 | myclass_fk
-------------------------
1 | abc | def | 2
2 | abc | def | 2
3 | abc | def | 1
MyClass2 Table
-------------------------
id | field3 | field4 | myclass_fk
-------------------------
1 | abc | def | 3
2 | abc | def | 1
3 | abc | def | 1
I tried to use #OneToMany on the list with targetType to MyInterface but it failed with error not a entity class.
EDIT
Can it be achieved with Hibernate OGM, preferably using graph or Mongo (document) based?
The problem is that Hibernate does not know from which table to load "mylist" when loading MyClass.
Take a look at https://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/domain/inheritance.html.
I could achieve this using #ManyToAny annotation, though I needed to modify the class bit.

JPA - Multiple columns discriminator

I have 3 tables like this in MySQL 5:
| PERSON |
| id | fullName | isEmp | isParent |
| EMPLOYEE |
| personId | code |
| PARENT |
| personId | job |
in which, Employee.personId and Parent.personId are foreign keys pointing to Person.id. An employee can also be a parent and vice versa. So how can I config using Annotation of JPA 2.0/Hibernate 3? Thanks!
If a Person can be both, you can't solve this through inheritance, because Java doesn't allow multiple inheritance. So you'll have to go with Aggregation, which is confusing on a semantic level, because it's has-a-parent instead of is-a-parent. But I'm afraid it's the way you'll have to go:
#Entity
public class Person{
#Id
private Long id;
#OneToOne(optional=true)
private Employee employee;
#OneToOne(optional=true)
private Parent parent;
public boolean isParent(){return parent!=null;}
public boolean isEmployee(){return employee!=null;}
}
#Entity
public class Employee{
#Id
private Long id;
#OneToOne(mappedBy="employee",optional=false)
private Person person;
}
#Entity
public class Parent{
#Id
private Long id;
#OneToOne(mappedBy="parent",optional=false)
private Person person;
}
(getters / setters etc. omitted)

Categories

Resources