Search JPA complex object for nested object based on its value - java

Lets assume we have a complex JPA relation, a fraction of which looks like this:
#MappedSuperclass
public class DiffEntity {
private String diffId;
public DiffEntity() {
this.diffId = UUID.randomUUID().toString();
}
//...
}
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class ParentEntity extends DiffEntity {
#Id
#GeneratedValue
private long id;
#Column
private String name;
//...
}
#Entity
public class Construct extends ParentEntity {
#Column
private String variable;
#OneToMany(mappedBy = "construct", cascade = CascadeType.ALL)
private List<Partconstruct> partconstructs;
//...
}
#Entity
public class Partconstruct extends ParentEntity {
#OneToMany(mappedBy = "partconstruct", cascade = CascadeType.ALL)
private List<Field> fields;
#OneToMany(mappedBy = "partconstruct", cascade = CascadeType.ALL)
private List<Hardparameter> hardparameters;
#ManyToOne
#JoinColumn(name = "construct_id")
private Construct construct;
//...
}
#Entity
public class Field extends ParentEntity {
#Column
private int fieldSize;
#ManyToOne
#JoinColumn(name = "partconstruct_id")
private Partconstruct partconstruct;
//...
}
#Entity
public class Hardparameter extends ParentEntity {
#Column
private String value;
#ManyToOne
#JoinColumn(name = "partConstruct_Id")
private Partconstruct partConstruct;
//...
}
We are concerned with Construct type objects. Construct is deeply cloned and persisted, having all its nested objects on the object graph being cloned too and getting a new Id (primary key). On every clone the diffId (from DiffEntity entity) stays the same (it serves the purpose of correlating objects for a diffing feature).
How would it be possible to search and get a reference for a specific DiffEntity given we have the below:
a reference to the Construnct instance
type of the nested object
diffId we are after.
I have tried different versions of object graph traversers with reflection, which will work for a small in size Construct object, but once it becomes too big performance is very slow.
Is there any magic on the entity manager itself to achieve that ?

Related

Error in jpa hibernate association many to one

This my Product class that extends a BaseClass and I get error in
#JoinColumn(name = "fk_supplier",referencedColumnName = "supplier_id")
private Supplier supplier;
and error is 'Many To One' attribute type should not be 'Supplier'
#Table
#Data
public class Product extends BaseEntity {
#ManyToMany
private List<Customer> customers = new ArrayList<>();
#ManyToOne
#JoinColumn(name = "fk_supplier",referencedColumnName = "supplier_id")
private Supplier supplier;
}
And this is my Supplier Class
#Table
#Data
public class Supplier extends BaseEntity {
#Column
private boolean active;
#Column
private Date foundationDate;
//Enum type to String type in mysql
#Column
#Enumerated(EnumType.STRING)
private Type type;
#OneToMany(targetEntity = Product.class)
private List<Product> products = new ArrayList<>();
}
supplier_id column is defined under which entity?, means in the provided snippet for Supplier entity no such field is present.
I hope the base entity will only be having columns that are generic and applicable over every entity you will be using. So if you specify referencedColumnName be sure that it align with what you have in the definitions. By default it will the primary key of the referenced entity, here primary key of Supplier table.
Please try to do like this, it may solve the issue i think
#JoinColumn(name = "fk_supplier")
private Supplier supplier;

Spring data Repositiry does not check for isNew(entity) on classes that are marked to be cascaded under the main entity

I have a parent class (for ease of understanding and running on your locals i have simplified the class structure)
#Entity
#Table(name = "entity_a")
public class EntityA implements Serializable, Persistable<Integer> {
#Id
#Column(name = "id")
private Integer id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "entity_b_id")
private EntityB entityB;
/* Getter and Setter */
#Override
public boolean isNew() {
return isNew;
}
}
#Entity
#Table(name = "entity_b")
public class EntityB implements Serializable, Persistable<String> {
#Id
#Column(name = "id")
private String id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy = "entityB")
private EntityA entityA;
/* Getters and Setters */
#Override
public boolean isNew() {
return isNew;
}
}
When I try to persist the new entity EntityA using the following spring data repository:
public interface EntityARepository extends JpaRepository<EntityA, Integer> {
}
it only checks for isNew on EntityA but ignores the isNew on EntityB and I keep getting primary key constraint errors on the persist operation
The reason why I am implementing the Persistable interface is because the EntityB is actually something that can be repeated quite a few times so I would like to check for its existence and set the isNew boolean accordingly before its saved
How do I make the spring repository take into account the isNew property of the child class as well that is marked to be cascaded

JPA OrderBy in #OneToMany by external field

I have entities:
#Entity
public class C {
#Column
private String name;
}
#Entity
public class B {
#Column
private Integer id;
#ManyToOne
#JoinColumn(name = "id_c")
private C c;
}
#Entity
public class A {
#OneToMany(mappedBy = "a")
#OrderBy("id")
private Set<B> itemsB;
}
Now when i access to A.itemsB() - items ordered by B.id
I need to get A.itemsB() ordered by C.name. Is this possible?
I tried to write something like #OrderBy("c.name") but it not work.
just check wich Order is imported : org.hibernate.annotations.OrderBy or javax.persistence.OrderBy.. you should use the second.
You should not use a 'Set<B>', but a 'List<B>'.Sets are always unordered.

one to many for same entity class in play framework

Good day!
I am triing to save my Entity model by always get an error
Error inserting bean [class models.CategoryEntity] with unidirectional relationship. For inserts you must use cascade save on the master bean [class models.CategoryEntity].]
Here my class
#Entity
public class CategoryEntity extends Model {
#Id
private String categoryId;
private String Name;
private Integer level;
#OneToMany(targetEntity = CategoryEntity.class, cascade = CascadeType.ALL)
private List<CategoryEntity> categories;
//GETERS SETRES
}
I tried to save the header category, but error is the same
If I understand the question correctly and what you want is that each CategoryEntity contains a list of other CategoryEntities, 2 possible approaches come to mind (although none of them use #OneToMany):
Approach 1:
You could create a #ManyToMany relationship and define a #JoinTable whilst naming its keys:
#Entity
public class CategoryEntity extends Model {
#Id
private String categoryId;
private String name;
private Integer level;
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable( name = "category_category",
joinColumns = #JoinColumn(name = "source_category_id"),
inverseJoinColumns = #JoinColumn(name = "target_category_id"))
public List<CategoryEntity> category_entity_lists = new ArrayList<CategoryEntity>();
}
Approach 2:
Or you could create a new entity for the list of category entities and create a #ManyToMany relationship, e.g.:
#Entity
public class CategoryList extends Model
{
#Id
public Long id;
#ManyToMany
#JoinTable(name="categorylist_category")
public List<CategoryEntity> category_list = new ArrayList<CategoryEntity>();
}
And then in your model:
#Entity
public class CategoryEntity extends Model {
#Id
private String categoryId;
private String name;
private Integer level;
#OneToOne
public CategoryList this_category_list;
#ManyToMany(mappedBy="category_list")
public List<CategoryList> in_other_category_lists = new ArrayList<CategoryList>();
}
Didn't test the code, but what this should do is that each CategoryEntity can be part of several CategoryLists. Each CategoryList contains a list of CategoryEntities.
You would have to initialize this_category_list and add CategoryEntities to its category_list field.
Your model doesnt make sense.
why do you have as class attribute the class itself?
the List should not be in the same class

How to model this with JPA?

I want to model a couple of object relations and I'm currently not sure about a smart way to do this. Let's assume a Record has a OneToMany relationship to different RecordSources. The common attributes of the RecordSources are long id and boolean preferred. Other attributes are individual and the number of record sources may increase in the future.
One possibility is for Record
#OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="record")
private List<GenericSimpleRecordSource> recordSources;
where GenericSimpleRecordSource would look like this:
#Entity
public class GenericSimpleRecordSource implements Serializable
{
public static enum Type {a,b}
#ManyToOne private Record record;
#NotNull
private Type sourceType;
#OneToOne(cascade = CascadeType.ALL,mappedBy="source")
private SimpleRecordSourceA sourceA;
#OneToOne(cascade = CascadeType.ALL,mappedBy="source")
private SimpleRecordSourceB sourceB;
}
SimpleRecordSourceA and SimpleRecordSourceA are individual #Entity classes. I don't feel comfortable with this approach, using inheritance might be better:
#Entity
#Inheritance(strategy= InheritanceType.TABLE_PER_CLASS)
#DiscriminatorColumn(name="type")
#DiscriminatorValue("generic")
public class GenericRecordSource
{
#Id #GeneratedValue(strategy=GenerationType.AUTO) private long id;
#ManyToOne private Record record;
private boolean preferred;
}
#Entity
#DiscriminatorValue("A")
public class RecordSourceA extends GenericRecordSource
{
...
}
#Entity
#DiscriminatorValue("B")
public class RecordSourceB extends GenericRecordSource
{
...
}
This seems to be smarter, but are there any shortcomings using Inheritance? I appreciate any comments on both approaches or even another alternative.
Is it possible to model the #OneToMany relationship from Record like this?
#OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="record")
private List<GenericRecordSource> recordSources;

Categories