I have 3 entity Unit, Off, Position. in my Unit have an constrain one to many with list offs, off have position. I want to Order by code in position.code, how can I make it
#Entity
#Table(name = "unit")
public class Unit{
#Id
#Column(name = "id")
private Long id;
#OneToMany(fetch = FetchType.LAZY)
#JoinClolumn(name = "unit")
#ElementCollection
#OrderBy("position.code")
private List<Off> offs;
}
this is my Entity Off
#Entity
#Table(name = "off")
#Embeddable
public class Off{
#Id
#Column(name = "id")
private Long id;
#Column(name = "cate_position")
private Long catePosition;
#ManyToOne
#NotFound(action = NotFoundAction.IGNORE)
#JoinClolumn(name = "cate_position")
#Embedded
private Position position;
}
this is my Entity Position
#Entity
#Table(name = "position")
#Embeddable
public class Position{
#Id
#Column(name = "id")
private Long id;
#Column(name = "code")
private String code;
}
How can I sort List offs in Unit entity by 'position.code', it always throws invalid column name 'position'. Many thanks!
Annotate the entity class Off with #Embeddable
and now include the following code above the List
#ElementCollection
#OrderBy("position.code DESC")
private List<Off> offs;
Related
I have following entities:
#Entity
#Getter
#Setter
#Table(name = "nomenclature", schema = "public")
public class Nomenclature implements Serializable {
#Id
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToMany
#JoinTable(name="nomenclature_versions",
joinColumns= #JoinColumn(name="nomenclature_id", referencedColumnName="id"))
private List<NomenclatureVersion> version;
}
and
#Entity
#Setter
#Getter
#Table(name = "nomenclature_versions", schema = "public")
#NoArgsConstructor
public class NomenclatureVersion implements Serializable {
#Id
#Generated(GenerationTime.INSERT)
#Column(name = "id")
private Long id;
#Column(name = "nomenclature_id")
private Long nomenclatureId;
#Column(name = "user_id")
private Long userId;
#Column(name = "creation_date")
private LocalDateTime creationDate;
#Column(name = "puls_code")
private String pulsCode;
#Column(name = "pic_url")
private String picUrl;
#Column(name = "current")
private boolean current;
}
When im trying to get Nomenclature with JPARepository getById(id) method im getting org.postgresql.util.PSQLException: ERROR: column version0_.version_id does not exist
It feels like the problem is around Hibernate Naming Strategies but i cant solve it.
Is there any other way to let Hibernate know which column should it use to join tables?
Don't use #JoinTable, the table is the same as the entity you are referencing. You just have to specify the #JoinColumn, hibernate will look for the column in the table referenced by the entity you are mapping the list to, NomenclatureVersion :
#OneToMany
#JoinColumn(name="nomenclature_id")
private List<NomenclatureVersion> version;
I'm working on a Spring-Boot project with a H2 database. I have two entities Portfolio and Report, and there is a many-to-many association between the two.
I want those entities to be audited, so I followed this tutorial to audit through an AuditorAware interface with custom fields.
The two entities are well audited, the columns are created in the database. However, the join table portfolio_reports is not audited. How can I audit the join table as well ?
Portfolio.java
#Entity
#Table(name = "portfolio")
public class Portfolio extends Auditable<String> implements Serializable {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
#Unique
private String name;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "portfolio_report", joinColumns = #JoinColumn(name = "portfolio_id"), inverseJoinColumns = #JoinColumn(name = "report_id"))
private List<Report> reports;
// Getters and setters
}
Report.java
#Entity
#Table(name = "report")
public class Report extends Auditable<String> implements Serializable {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "axioma_id")
private Long axiomaId;
#Column(name = "name")
private String name;
#AuditJoinTable
#ManyToMany(mappedBy = "reports", cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
private List<Portfolio> portfolios;
// Getters and setters
}
Auditable.java
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class Auditable<U> {
#Version
#Column(name = "version_no")
protected Long versionNo;
#CreatedDate
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_date")
protected Date createdDate;
#LastModifiedDate
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "modified_date")
protected Date modifiedDate;
}
AuditorAwareImpl.java
public class AuditorAwareImpl implements AuditorAware<String> {
#Override
public Optional<String> getCurrentAuditor() {
return Optional.of("Admin");
}
}
PersistenceConfiguration.java
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class PersistenceConfiguration {
#Bean
public AuditorAware<String> auditorAware() {
return new AuditorAwareImpl();
}
}
Problem:
Clearly here Auditable should add some column to your intermediate table that maintains relation between Portfolio and Report and that table is created behind the scene and you don't have access to that table in your program. Only hibernate can use that table to maintain relation between your entities and do join operation.
Solution:
Here you should make Join table that maintain Many to Many relation between Portfolio and Report explicit so that you can have entity like PortfolioReport in your program that can extends from Auditable. Please read the following post to see how to do that: The best way to map a many-to-many association with extra columns when using JPA and Hibernate
I work with an embedded H2 database in which I use the #OneToMany relationship to relate an entity instance (product) to multiple instances of the other entities (suppliers); it's useful when I have specific suppliers for a particular product.
However now, I want to associate all the suppliers with every single product; I don't want to generate in my supplier table different supplier records for each product, instead I want to have only 5 records (5 suppliers) in my supplier table which are associated to every single product, it few words I want to achieve something like "one to all", is it possible to do it using JPA annotations?
Product entity
#Entity
public class Product {
#Id
private String productCode;
#OneToMany
#JoinColumn(name = "supplier_id", referencedColumnName = "productCode")
private List<Supplier> suppliers;
}
Supplier entity
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
private String name;
}
Unidirectional #OneToMany association:
#Entity
public class Product {
#Id
// #Column(name = "id") maybe
// #GeneratedValue maybe
private String productCode;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) // according to your need
private List<Supplier> suppliers;
...
}
And,
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
...
}
#ManyToOne association:
#Entity
public class Product {
#Id
// #Column(name = "id") maybe
// #GeneratedValue maybe
private String productCode;
...
}
And,
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name = "product_id", foreignKey = #ForeignKey(name = "PRODUCT_ID_FK"))
private Product product;
private String name;
...
}
I am working on hibernate and tying to associate mapping with #OneToMany relationship with composite key.
Following are the entities that currently my using .
#Embeddable
#Getter
#Setter
public class AddressKey implements Serializable {
private static final long serialVersionUID = -307823488229761699L;
#Column(name = "id")
private Long id;
#Column(name = "city")
private Long city;
#Column(name = "locale")
private String locale;
#Column(name = "type")
private String type;
#ManyToOne
#JoinColumn(name="id")
private Person person;
}
#Entity
#Table(name = "address", schema = "test")
#Setter
#Getter
public class AddressHistory {
#EmbeddedId
private AddressKey key;
#Column(name = "active")
private boolean active;
#Column(name = "current")
private boolean current;
}
#Entity
#Table(name = "person", schema="test")
#ToString
public class Person {
#Id
#Column(name = "id")
private Long id;
#OneToMany(mappedBy="key.person", fetch=FetchType.EAGER, cascade=CascadeType.ALL)
private Set<AddressHistory> addressHistory;
}
But when I am trying to run this program it gives me following error.
repeated column in mapping for entity AddressHistory.
Someone help me to fix this what's wrong in this mapping.
Thanks in advance
You repeated columns. Remove #JoinColumn(name="id") in AddressKey since you already have one column with the same name or rename it to something else and more maintainable like person_id.
Suppose, we have two entities, first one:
#Entity
#Table(name = "entitya")
public class EntityA {
#Id
#Column(name = "id")
private Long id;
#Column(name = "name")
private Long name;
#OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private Set<EntityB> childEntities;
}
and the second:
#Entity
#Table(name = "entityb")
public class EntityB {
#Id
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#Column(name = "master")
private Boolean master;
#ManyToOne
#JoinColumn(name = "parent")
private EntityA parent;
}
So far, so good. However underlying database tables and constrains enforce that for any entityA there can be only one EntityB with boolean field master set to true. I can extract it by adding following method to entityA:
public entityB getMasterChild() {
for(entityB ent : childEntities) {
if(ent.isMaster()) {
return ent;
}
}
}
The question is, can I create #OneToOne relationship in EntityA that can express that rule, so that entityA can have additional masterChild member of type entityB?
If I understood you correctly you want to create/define a relationship between two entities based on a value of some entity's property. The think is that relationship between entities is defined on entities count (how many entities can has the other entity) and not on some entity's property value.
However
If you really want to use #OneToOne mapping for masterChild I would recommend creating a separate table/entity for it. Once this is done, you can include this new MasterChild entity into EntityA and annotate it with #OneToOne.
Here is new MasterChild entity
#Entity
public class MasterChild extends EntityB{
#Id
#Column(name = "id")
private Long id;
}
Note that I have removed 'master' from EntityB as it is no longer needed
#Entity
#Table(name = "entityb")
public class EntityB {
#Id
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#ManyToOne
#JoinColumn(name = "parent")
private EntityA parent;
}
And here is modified EntityA
#Entity
#Table(name = "entitya")
public class EntityA {
#Id
#Column(name = "id")
private Long id;
#Column(name = "name")
private Long name;
#OneToOne
private MasterChild master;
#OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private Set<EntityB> childEntities;
}