spring boot Mapstruct joined table inheritance mapping - java

I have Person, Customer and Worker classes. So worker and customer classes extends Person class
#Entity
#Table(name = "person")
#Getter
#Setter
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Person
#Entity
#Getter
#Setter
#Table(name = "customer")
public class Customer extends Person
#Entity
#Getter
#Setter
#Table(name = "worker")
public class Worker extends Person
`
How can I write mapping classes for this.
I only trying this:
#Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring")
public interface CustomerMapper {
Customer toEntity(CustomerDTO customerDto);
CustomerDTO toDto(Customer customer);
#BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
Customer partialUpdate(CustomerDTO customerDto, #MappingTarget Customer customer);`

Related

Creating many to many table per entity while dealing with generics

I am trying to create a generic JPA entity class that, when extended, would create a separate table for each extended entity class and also create per-entity, separate, many-to-many table for the relationships included to the generic type. I have accomplished the first step - to create per-entity tables for the general entities, but I can't figure out how I could create the corresponding many-to-many tables per class.
Here is the model and some explanation:
A #MappedSuperclass entity class for every entity in the model:
#Getter
#Setter
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "Id", nullable = false, updatable = false)
private long id;
}
An abstract class for extending the BaseEntity with the saving time and user. This is a separate class, because this is not present in some other model classes (unrelated to this issue).
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Getter
#Setter
public abstract class EntityWithSaveData extends BaseEntity {
// omitted unrelated fields...
}
A few model classes representing "linkages" that extend the abstract Linkage entity.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Getter
#Setter
public abstract class Linkage extends EntityWithSaveData {
// omitted unrelated fields...
}
#Table
#Entity(name = "LinkageA")
#Getter
#Setter
#NoArgsConstructor
public class LinkageA extends Linkage {
#OneToMany(mappedBy = "root")
private Collection<LinkageGroup<LinkageA>> allRoot = new ArrayList<>();
#ManyToMany(mappedBy = "children")
private Collection<LinkageGroup<LinkageA>> allChildren = new ArrayList<>();
}
#Table
#Entity(name = "LinkageB")
#Getter
#Setter
#NoArgsConstructor
public class LinkageB extends Linkage {
#OneToMany(mappedBy = "root")
private Collection<LinkageGroup<LinkageB>> allRoot = new ArrayList<>();
#ManyToMany(mappedBy = "children")
private Collection<LinkageGroup<LinkageB>> allChildren = new ArrayList<>();
}
And linkage groups. There is an abstract, generic LinkageGroup class with a "root" and "children". For each "linkage" entity there is a "linkage group" entity that extends the LinkageGroup.
#Entity(name = "LinkageGroup")
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Getter
#Setter
public abstract class LinkageGroup<T extends Linkage> extends EntityWithSaveData {
#ManyToOne(targetEntity = Linkage.class)
#JoinColumn(name = "IdRootLinkage", nullable = false)
private T root;
#ManyToMany(targetEntity = Linkage.class)
private Collection<T> children = new ArrayList<>();
}
#Table
#Entity(name = "GroupA")
#Getter
#Setter
#NoArgsConstructor
public class GroupA extends LinkageGroup<LinkageA> {
// omitted unrelated fields...
}
#Table
#Entity(name = "GroupB")
#Getter
#Setter
#NoArgsConstructor
public class GroupB extends LinkageGroup<LinkageB> {
// omitted unrelated fields...
}
While Hibernate creates the "linkages" and "groups" tables just fine, the "group children" are created as a single table, that I would like to avoid and I would prefer a table per LinkageGroup entity.
Here is the generated database tables list
Is there a way to achieve what I am trying to do in this case?

How to refactor abstract Inheritance structure into SuperBuilder in Java?

We have a base class
#SuperBuilder(toBuilder = true)
#Getter
#Setter
#EqualsAndHashCode
#AllArgsConstructor
#NoArgsConstructor
#MappedSuperclass
public class BaseEntity {
private UserEntity createUser;
private LocalDateTime createDate;
}
And an abstract class which extends this base class:
#SuperBuilder(toBuilder = true)
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity(name = "COMPANY")
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class CompanyEntity extends BaseEntity {
#EqualsAndHashCode.Include
#Id
#GeneratedValue
private UUID id;
#Builder.Default
#Fetch(FetchMode.SUBSELECT)
#ManyToMany(mappedBy = "companies", fetch = FetchType.LAZY)
private Set<UserEntity> users = new HashSet<>();
}
With two classes extending the abstract class that look like this
#SuperBuilder(toBuilder = true)
#Entity(name = "SPECIAL")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class SpecialEntity extends CompanyEntity {
#NotBlank
private String customerName;
private String somethingUnimportant;
}
We have to remove the #Entity(name = "COMPANY") in order for the SuperBuilder to work. Our current #Inheritance(strategy = InheritanceType.JOINED) will therefore no longer work to combine the sub-entities into one table in the database.
How is it possible to keep the current database structure, but change to include the SuperBuilder constructor?
Is #jan-rieke around? :D

How to avoid to duplicate a jpa mapping (entity, service, repository..) if same table but different schemas?

I am using jpa and have 2 entities, but in this situation :
Entity A = schemaA.tableX
Entity B = schemaB.tableX
tableX is the same but duplicated on 2 different schemas (A and B), same columns inside, and I am supposed to fill them with same data through my application.
The question is : is it possible in my code, to mappe once this tableX and somehow, data will be splited on two, one for each schema ??
I do not want :
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "TableX", schema = "A")
public class A implements Serializable {
#Id
#Column(name = "id")
private String id; <=== on table A
}
And :
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "TableX", schema = "B")
public class B implements Serializable {
#Id
#Column(name = "id")
private String id; <=== on table B
}
A dumb copy/past of : entity, repository, service, impl... because exactelly the same Table !
You could do that probably with a #MappedSuperClass:
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#MappedSuperClass // <-- see this annotation
public class AbstractTable implements Serializable { // <-- name the class however you want
#Id
#Column(name = "id")
private String id;
}
And then change your two other classes to this:
#Entity
#Table(name = "TableX", schema = "A")
public class A extends AbstractTable {}
And
#Entity
#Table(name = "TableX", schema = "B")
public class B extends AbstractTable {}

Lombok #Builder with Inheritance and JPA

I have this class:
#Entity
#Table(name = "PERSONNE")
#Inheritance(strategy = InheritanceType.JOINED)
#NoArgsConstructor
#AllArgsConstructor
#Data
#SuperBuilder
#ToString
#EqualsAndHashCode(of = { "personneId" })
public class Personne implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "PERSONNE_ID")
protected Long personneId;
}
and this other one
#Entity
#Table(name = "DISSIDENT")
#PrimaryKeyJoinColumn(name = "PERSONNE_ID")
#Data
#SuperBuilder
#NoArgsConstructor
#AllArgsConstructor
#ToString(callSuper = true)
#EqualsAndHashCode(callSuper = true)
public class Dissident extends Personne {
private static final long serialVersionUID = 1L;
}
but when I run a test I got this error:
java: constructor Dissident() is already defined in class com.bar.peris.model.Dissident
Try changing the order of #NoArgsConstructor
#AllArgsConstructor. Class by default have a no arg constructor unless a constructor is defined.

Spring-Data-Neo4j: relationshipEntity return only graphId for nodes.

I am creating an example using Spring-Data-Neo4j . In this, perform CRUD operations, and all operation run successfully. But when i fetch the relationa ship collection from entity, it return only graphId for nodes, and other values are null. Following is my code. If i do something wrong, please correct me.
Entities:
#NodeEntity
#ToString(callSuper=true, exclude={"movies"})
#EqualsAndHashCode(callSuper = true, exclude = {"name", "movies"})
public class Person extends BaseEntity{
#Getter #Setter
#Indexed(unique = true)
private Long id;
#Getter #Setter
private String name;
#Getter #Setter
#RelatedToVia(type = RelationshipTypes.FRIEND, elementClass = FriendsRelationship.class, direction = Direction.BOTH)
private Set<FriendsRelationship> friends;
}
#RelationshipEntity(type=RelationshipTypes.FRIEND)
public class FriendsRelationship extends BaseEntity{
#StartNode
#Getter #Setter
private Person person;
#EndNode
#Getter #Setter
private Person friend;
#Getter #Setter
private String friendsType;
}
Create Relationship:
public FriendsRelationship createRelationshipBetweenPersons(Person person, Person friend,
Class<FriendsRelationship> relationshipEntity, String friendshipType) {
FriendsRelationship relationship = neo4jTemplate.createRelationshipBetween(person, friend, relationshipEntity, friendshipType, true);
neo4jTemplate.save(relationship);
return relationship;
}
Controller:
#RequestMapping(value="find-person-by-id", method=RequestMethod.POST)
public String findPersonById(long id, Model model) {
Person person = personService.findPersonByProperty("id", id);
model.addAttribute("actor", person);
model.addAttribute("personFriends", person.getFriends());
return "person/view-person-detail";
}
In controller, when i fetch the person, the person fetch successfully, but i fetch the friends, it contain start_node with same person object, but end_node contain person object with graphId value only, others values are null.
For solve this problem, we need to add #Fetch annotation at start-node and end-node in FriendsRelationship entity, like as below:
#RelationshipEntity(type=RelationshipTypes.FRIEND)
public class FriendsRelationship extends BaseEntity{
#Fetch #StartNode
#Getter #Setter
private Person person;
#Fetch #EndNode
#Getter #Setter
private Person friend;
#Getter #Setter
private String friendsType;
}
Now the data fetch successfully.

Categories