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;
Related
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;
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.
I have one entity and I want to track all changes therefore I created new Entity for audit.
Below is my primary entity:
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name = "primary")
public class PrimaryEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "primary_id")
private Long id;
private String name;
#LazyCollection(LazyCollectionOption.FALSE)
#ElementCollection
#CollectionTable(
name = "primary_attachments",
joinColumns = #JoinColumn(name = "primary_id")
)
private List<String> attachments;
#CreatedDate
#Temporal(TemporalType.DATE)
private Date createDate;
#LastModifiedDate
#Temporal(TemporalType.DATE)
private Date lastModifiedDate;
}
And below is my entity for audit:
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name = "primary_audit")
public class PrimaryEntityAudit {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "audit_id")
private Long id;
#NotNull
#Column(name = "primary_entity_id")
private Long primaryId;
private String name;
#LazyCollection(LazyCollectionOption.FALSE)
#ElementCollection
#CollectionTable(
name = "primary_attachments_audit",
joinColumns = #JoinColumn(name = "primary_entity_id")
)
private List<String> attachments = new ArrayList<>();
#CreatedDate
#Temporal(TemporalType.DATE)
private Date createDate;
public PrimaryEntityAudit(PrimaryEntity primaryEntity) {
this.primaryId = primaryEntity.getId();
this.attachments.addAll(primaryEntity.getAttachments());
this.createDate = new Date();
}
}
And before update primary entity I create new PrimaryEntityAudit and save this object and then update the primary entity.
And operation is successful and object PrimaryEntityAudit is saved, but attachments from PrimaryEntityAudit aren't saved.
I tried also in constructor of ProjectEntityAudit do setAttachments, but then I got an Exception: HibernateExcpetion: Found shared references to collection.
How should I map the collections of audit for saving old state of PrimaryEntity attachments?
You should look at the following hibernate module Envers
It provides features for versioning and auditing
It is preferable to not reinvent the wheel except if you have technicals constraints which prevent you to use some frameworks or others.
I'm trying to build a multi-language database, so I've used this database design as a approach for mine.
Now I've two problems/questions:
I want to retrieve all LocalizedEvent for a given language and given categoryId. How can I make a inner join over the LocalizedCategory table with Hibernate Criteria API?
With SQL I would make this statement to get all LocalizedEvent + LocalizedCategory:
SELECT * FROM event e
INNER JOIN
localized_event le ON (le.event_id = e.event_id)
INNER JOIN
localized_category lc ON (lc.category_id = e.category_id)
WHERE
le.locale = 'de' AND lc.locale = 'de'
My current approach looks like this without getting the LocalizedCategory (with Criteria API):
Criteria c = session.createCriteria(LocalizedEvent.class, "localizedEvent");
c.createAlias("localizedEvent.event", "event");
c.createAlias("event.category", "category");
c.add(Restrictions.eq("category.categoryId", categoryId));
c.add(Restrictions.eq("localizedEvent.locale", language));
I think my mapping is not 100% correct. The entity LocalizedEvent should have a property localizedCategory, but I don't want to save the ID of this localizedCategory (therefore I'm using the #Transient annotation) in the LocalizedEvent table, e.g. using a ManyToOne relation (joining LOC_CATEGORY_ID). But I think it's not possible to do this, isn't it? I would have to map this transient field to LocalizedEvent "manually", because Hibernate is not supporting this mapping (if I'm right).
(Using JDBC this property/mapping would cause no problems, because I can easily make my inner joins and assign the property localizedCategory to the LocalizedEvent in a RowMapper or so).
My entities looks like this:
Event
#Entity
#Table(name = "EVENT")
public class Event {
#Id
#GeneratedValue
#Column(name = "EVENT_ID", unique = true)
private Long eventId;
#Column(name = "DATE")
private Date date;
#OneToMany(mappedBy = "event")
private Set<LocalizedEvent> localizedEvents;
#ManyToOne
#JoinColumn(name = "CATEGORY_ID")
private Category category;
}
LocalizedEvent
#Entity
#Table(name = "LOCALIZED_EVENT")
public class LocalizedEvent {
#Id
#GeneratedValue
#Column(name = "LOC_EVENT_ID")
private Long locEventId;
#ManyToOne
#JoinColumn(name = "EVENT_ID")
private Event event;
#Transient
private LocalizedCategory localizedCategory;
#Column(name = "DESCRIPTION")
private String description;
#Column(name = "LOCALE")
private String locale;
}
Category
#Entity
#Table(name = "CATEGORY")
public class Category {
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID", unique = true)
private Long categoryId;
#OneToMany(mappedBy = "category")
private Set<LocalizedCategory> localizedCategories;
#OneToMany(mappedBy = "category")
private Set<Event> events;
}
LocalizedCategory
#Entity
#Table(name = "LOCALIZED_CATEGORY")
public class LocalizedCategory {
#Id
#GeneratedValue
#Column(name = "LOC_CATEGORY_ID")
private Long locCategoryId;
#ManyToOne
#JoinColumn(name = "CATEGORY_ID")
private Category category;
#Column(name = "NAME")
private String name;
#Column(name = "LOCALE")
private String locale;
}
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;
}