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.
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 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 have a very large json to store and I divided that into following five entities and trying to store to h2 database using spring-data-jpa,inserting is working fine into database, but while fetching A object with A primary key Id, I am getting stackoverflow error, because there is circular dependency.
could someone help me to figure out what is the issue.
Top class
#Entity
#Table(name = "a")
#Data
public class A{
#Id
#Column(name = "a_id")
private String id;
#Column
private String name;
#Column
private String name2;
#Column
private String name3;
#Column
private String name4;
#Column
private String name5;
#OneToMany(cascade = CascadeType.ALL,mappedBy = "a",fetch =
FetchType.EAGER)
#JsonManagedReference
private List<B> b;
}
Second class
#Entity
#Table(name = "b")
#Data
public class B{
#Id
#Column(name = "bname")
private String bname;
#Column
private String bVersion;
#OneToMany(cascade = CascadeType.ALL,mappedBy = "b")
#JsonManagedReference
private List<C> cs;
#ManyToOne
#JoinColumn(name = "a_id")
#JsonBackReference
private A a;
}
Third class
#Entity
#Data
public class C{
#Id
#Column(name = "cname")
private String cName;
#Column
private String cVersion;
#OneToMany(cascade = CascadeType.ALL,mappedBy = "c")
#JsonManagedReference
private List<D> ds;
#ManyToOne
#JoinColumn(name = "bname")
#JsonBackReference
private B b;
}
Fourth class
#Entity
#Data
public class D{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="d_id")
private long id;
#Column
private String dName;
#Column
private String dName2;
#ElementCollection
#Column
private List<String> dNames;
#OneToMany(cascade = CascadeType.ALL,mappedBy = "d")
#JsonManagedReference
private List<E> e;
#ManyToOne
#JoinColumn(name = "cname")
#JsonBackReference
private C c;
}
Fifth class
#Entity
#Data
public class E{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "e_id")
private long id;
#Column
private String ename;
#Column
private String eName2;
#ManyToOne
#JoinColumn(name = "e_id")
#JsonBackReference
private E e;
}
I also faced the same problem and spent the whole day. Finally, I found its problem with the toString method generated by Lombok using #Data annotation.
Solution:
Override, toString method and write your own implementation. If you do not want to use toString then use #Getter and #Setter instead of #Data.
Why
Note: This occurs with bi-directional relationship.
Lets say I have two entity and having bi-directional relationship.
#data
Entity1{
#oneToMany
public List<Entity2> entity2s;
//Added by lombok while using #Data
#Generated
public String toString() {
return "entity2s=" + this.getEntity2s() + ")";
}
}
#data
Entity2{
#ManytoOne
public Entity1 entity1;
//Added by lombok while using #Data
#Generated
public String toString() {
return "entity1=" + this.getEntity1() + ")";
}
}
In above example, toString()(called by JPA) of Entity1 calles toString() of Entity2 and toString() of Entity2 calls toString() of Entity1. And that is how circular reference is building.
Note: The same goes to hashCode method.
Here is a some reference links,
https://github.com/rzwitserloot/lombok/issues/1007
https://interviewbubble.com/stackoverflow-tostring-method-when-using-lombok/
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;
}
Is this possible? Haven't seen much discussion on it.
Sure! It works great from my experience. Here's an example entity:
#Entity
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class PingerEntity {
// ID
#Id
#Getter
#Setter
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// USER
#Getter
#Setter
#ManyToOne(fetch = FetchType.LAZY, optional = false)
private UserEntity user;
// URL
#Getter
#Setter
#Basic(optional = false)
private String url;
/**
* The number of seconds between checks
*/
#Getter
#Setter
#Basic(optional = false)
private int frequency;
#Getter
#Setter
#Basic(optional = false)
#Enumerated(EnumType.STRING)
public MonitorType monitorType;
}
You can use it also with #Data (and it works !)
#Entity
#Data
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
}
I have never tried Lombok with Hibernate but I don't see why it shouldn't work.
Also, take a look here: http://groups.google.com/group/project-lombok/browse_thread/thread/294bd52d9d8695df/7bc6b0f343831af1?lnk=gst&q=hibernate#7bc6b0f343831af1
Also, Lombok project release notes mention Hibernate explicitely.
A simple example; Library.java:
#Data
#NoArgsConstructor // JPA
#Entity
#Table(name = "libraries")
public class Library {
#Id
#GeneratedValue
private Long id;
#OneToMany(cascade = CascadeType.ALL)
#EqualsAndHashCode.Exclude
// This will be included in the json
private List<Book> books = new ArrayList<>();
#JsonIgnore
public void addBook(Book book) {
books.add(book);
book.setLibrary(this);
}
}
And Book.java:
#Data
#NoArgsConstructor // JPA
#Entity
#Table(name = "books")
public class Book {
#Id
#GeneratedValue
private Long id;
#NotBlank
private String title;
#ManyToOne
#JoinColumn(name = "library_id") // Owning side of the relationship
#EqualsAndHashCode.Exclude
#JsonIgnore // Avoid infinite loops
private Library library;
}