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
Related
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?
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 {}
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.
For example, I have a Job entity and a worker entity.
when I add new job I want to assign workers to it but instead of adding it's users to
the database again ( and create duplicates ) I want to just update workers
( add jobs to them when I create a new job with worker list )
example :
#Entity
#Table(name = "job")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Job{
#Id
#Column(name = "id")
private Long id;
#OneToMany(mappedBy = "job", fetch = FetchType.EAGER)
private Set<Worker> workers;
}
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "workers")
public class User extends DataAudit {
#Id
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "job_id", referencedColumnName = "id")
private Job job;
}
Worker worker1 = workerService.getWorkerById(1);
Job job = new Job(1,worker1)
jobRepo.save(job)
The entities should be using bidirectional OneToMany association with #JoinTable:
#Entity
#Table(name = "job")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Job{
#Id
#Column(name = "id")
private Long id;
#OneToMany(fetch=FetchType.LAZY)
#JoinTable(name="job_workers",
joinColumns={#JoinColumn(name="job_id")},
inverseJoinColumns={#JoinColumn(name="worker_id")}
)
#Cascade(org.hibernate.annotations.CascadeType.ALL)
private Set<Worker> workers;
}
////////////////////////////////////////////////////////
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "workers")
public class User extends DataAudit {
#Id
private Long id;
#ManyToOne
#JoinTable(name="job_workers",
joinColumns={#JoinColumn(name="worker_id", insertable=false,updatable=false)},
inverseJoinColumns={#JoinColumn(name="job_id", insertable=false,updatable=false)})
private Job job;
}
I have 2 entity with MAnyToMany relationship.
#Entity
#Table(name = "PP_CONFIG")
public class PricePlanConfig {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
#Getter #Setter private Long id;
#Getter #Setter private String Name;
#Getter #Setter private String wfaId;
#Getter #Setter private Integer status;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#Getter #Setter private List<PricePlanCrm> ppCrm;
and
#Entity
#Table(name = "PP_CRM")
#EqualsAndHashCode(exclude={"id", "ppConfig"})
public class PricePlanCrm {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Getter #Setter private Long id;
#Getter #Setter private String rkId;
#Getter #Setter private String name;
#Getter #Setter private String priceplantype;
#Getter #Setter private String enabled;
#ManyToMany(mappedBy = "ppCrm")
#Getter #Setter private List<PricePlanConfig> ppConfig;
I want update
#Getter #Setter private List<PricePlanCrm> ppCrm;
And i do it
public void updatePricePlainsToCurrentPricePlaneConfig(){
List<PricePlanCrm> pricePlansClear = getPricePlansClear();
currentPricePlanConfig.setPpCrm(pricePlansClear);
PricePlanCrmDaoImpl.me().merge(currentPricePlanConfig);
}
in pricePlansClear I have 3 new values and in currentPricePlanConfig.setPpCrm() I have 7 old values. Ifter update/merge I want 3 new values in my currentPricePlanConfig. But not happend. I do not have errors but new values not set to currentPricePlanConfig.
If I add new value to current - it added.
But I want remove all old values and set all new values.