I have these BaseNews and News entity:
#MappedSuperclass
public class BaseNews extends Model {
public static Model.Finder<Long, News> find = new Model.Finder<Long, News>(News.class);
public static News getNewsById(Long newsId) {
return find.byId(newsId);
}
public static List<News> getNewsList(int pageIndex, int pageSize) {
return find.where()
.findPagedList(pageIndex, pageSize)
.getList();
}
}
#Entity
#Table(name = "news")
public class News extends BaseNews implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// #ManyToOne
// private News baseNews;
#OneToMany(cascade = CascadeType.ALL)//,mappedBy = "baseNews")
#JoinTable(name = "news_similar",
joinColumns = {#JoinColumn(name = "base_news_id")},
inverseJoinColumns = {#JoinColumn(name = "similar_news_id")}
)
private List<News> similarNews;
//getters, setters...
}
In both uni and bidirectional case
select t0.id c0, t0.base_news_id c1 from news t0
gives error Unknown column base_news_id
Am I doing it wrong way?
Should I create new Entity NewsSimilar instead of using jointable?
Actually I am reversing existing table.
create table news_similar
(
id int auto_increment primary key,
base_news_id int not null,
similar_news_id int not null,
constraint news_similar_ibfk_1 foreign key (base_news_id) references news (id) on update cascade on delete cascade,
constraint news_similar_ibfk_2 foreign key (similar_news_id) references news (id) on update cascade on delete cascade
)
Edit: news_id was completely unrelated problem from other field, anyway solved it.
It turns out that I have ManyToMany relation so, the solution is like this
#Entity
#Table(name = "news")
public class News extends BaseNews implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "news_similar",
joinColumns = {#JoinColumn(name = "base_news_id")},
inverseJoinColumns = {#JoinColumn(name = "similar_news_id")}
)
private List<News> similarNews;
//getters, setters...
}
Came by this solution while reading this article:
https://www.thoughts-on-java.org/ultimate-guide-association-mappings-jpa-hibernate/
Related
how do i create entity for area_item_table which have foreign key as primary key
the Item entity:
#Entity
#Table(name = Item.ITEM)
public class Item {
#Id
#Column(name = ITEM_ID)
private long itemId;
#OneToOne
#JoinTable(name = "area_item_table",
joinColumns = {#JoinColumn(name = ITEM_ID, referencedColumnName = ITEM_ID)},
inverseJoinColumns = {
#JoinColumn(name = AREA_ID, referencedColumnName = ID)})
private Area area;
[removed get set and unrelated fields from entity]
}
the Area entity:
#Entity
#Table(name = Area.AREA)
public class Area {
#Id
#Column(name = ID, nullable = false)
private Long id;
[removed get set and unrelated fields from entity]
the table area_item_table :
item_id
area_id
1
121
is there a way to create an Entity for this table without creating new primary key field
I am currently trying to extract a set of entities from a table with a composite key, but I only want to perform the join with id_a to get a set and not both(id_a and id_b) which would yield a single result.
This is not the original code, but it is an example of what I am trying to achieve.
#Entity
public class ItemA {
#EmbeddedId
private ItemId itemId;
#OneToMany
private Set<ItemB> itemsB = new HashSet<>();
}
#Embeddable
public class ItemID implements Serializable {
private Integer itemIDA;
private Integer itemIDB;
}
#Entity
public class ItemB {
#Id
private Integer itemIDA;
}
I have tried a couple of ways, mainly annotating the #OneToMany with #JoinColumn and also with #JoinTable
#OneToMany
#JoinTable(
name = "itemB",
joinColumns = { #JoinColumn(name = "itemIDA") },
inverseJoinColumns = { #JoinColumn(name = "itemIDA") }
)
private Set<ItemB> detalleUsuarios = new HashSet<>();
also I tried maybe trying to get inside of the ItemId class
#OneToMany
#JoinTable(
name = "itemB",
joinColumns = { #JoinColumn(name = "itemID.itemIDA") },
inverseJoinColumns = { #JoinColumn(name = "itemIDA") }
)
private Set<ItemB> detalleUsuarios = new HashSet<>();
But I get the following error
A Foreign key refering com.example.ItemA from com.example.ItemB has the wrong number of column. should be 2
I have a problem when cascade deleting my Parent entity:
org.postgresql.util.PSQLException: UPDATE or DELETE on table "child" violates constraint "XXX": for key (id)=(4) there are references in table "child_properties"
#Entity
#Table(name = "Parent")
public class Parent{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(fetch = FetchType.EAGER,mappedBy = "parent")
#OnDelete(action = OnDeleteAction.CASCADE)
private Set<Child> children;
}
#Entity
#Table(name = "child")
public class Child{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "parent_id")
private Parent parent;
#ElementCollection(fetch = FetchType.EAGER)
private Map<String,String> properties;
}
I expected child to delete its properties on parentRepository.delete(parent)
but this only happens on childRepository.delete(child). parent delete throws exception
the solution was ~3 hours googling...
the idea is to set custom foreign key
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "child_properties"
,joinColumns = {
#JoinColumn(name = "child_id"
, referencedColumnName = "id"
,foreignKey=#ForeignKey(name="CHILD_PROPERTY_FK"
, foreignKeyDefinition = "FOREIGN KEY (child_id) references public.child (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE"))
}
)
#MapKeyColumn(name = "name")
#Column(name = "value")
private Map<String,String> properties;
How fix next error?
ERROR SchemaExport:484 - HHH000389: Unsuccessful: alter table CATEGORY_RELATIONS add constraint FK2bn4xlg661b5xbx2qnwi1aqv0 foreign key (CATEGORY_RELATIONS_PARENT_ID) references CATEGORY
ERROR SchemaExport:485 - incompatible data types in combination in statement [alter table CATEGORY_RELATIONS add constraint FK2bn4xlg661b5xbx2qnwi1aqv0 foreign key (CATEGORY_RELATIONS_PARENT_ID) references CATEGORY]
hibernate.version 5.0.7.Final
hsqldb.version 2.3.3
Property, used for session factory
hibernate.dialect=org.hibernate.dialect.HSQLDialect
Category
#Entity
#Table(name = "CATEGORY",
indexes = {
#Index(name = "CATEGORY_NAME_INDEX",
columnList = "CATEGORY_NAME")})
public class Category extends JsonNamedModel {
#Id
#Column(name = "CATEGORY_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "CATEGORY_NAME")
private String name;
#Column(name = "CATEGORY_IMAGE")
private String image;
#OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
#JoinTable(name = "CATEGORY_RELATIONS",
joinColumns = {
#JoinColumn(name = "CATEGORY_RELATIONS_CATEGORY_ID", referencedColumnName = "CATEGORY_ID")},
inverseJoinColumns = {
#JoinColumn(name = "CATEGORY_RELATIONS_PARENT_ID", referencedColumnName = "CATEGORY_ID")})
private Category parent;
#OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy = "parent")
private List<Category> children;//...
}
CategoryRelations
#Entity
#Table(name = "CATEGORY_RELATIONS")
#IdClass(CategoryRelations.CategoryRelationsPrimaryKey.class)
public class CategoryRelations implements Serializable {
#Id
#Column(name = "CATEGORY_RELATIONS_CATEGORY_ID")
private String categoryId;
#Id
#Column(name = "CATEGORY_RELATIONS_PARENT_ID")
private String parentId;
#Entity
#IdClass(CategoryRelationsPrimaryKey.class)
public static class CategoryRelationsPrimaryKey implements Serializable {
private long categoryId;
private long parentId;
}//...
}
I think it's complaining because your types don't match up. In CATEGORY_RELATIONS you have the key types as String but in CATEGORY you have the primary key as an int. While in actual practice you might only store integer data in both fields, the DB engine can't prove that. There's nothing stopping somebody from putting a non-integer in CATEGORY_RELATIONS.categoryId and making it so the FK could never be satisfied.
Try changing CATEGORY_RELATIONS.categoryId to an int.
And now that I look at it, your PK class shows them as longs. Try switching all of the types in your CategoryRelations object (and possibly the CATEGORY_RELATIONS table) to all be the same types.
I have an existing database modeled the following way:
Student - SchoolId(PK), StudentId(PK), StudentName
Teacher - SchoolId(PK), TeacherId(PK), TeacherName
Student_Teacher - SchoolId(PK), StudentId(PK), TeacherId(PK)
Foreign key references exist from Student_Teacher to respective entities.
Now I am creating hibernate entities for this existing database. And I am running into weird issues creating Many-to-Many mapping from Student to Teacher.
#Entity
#Table(name = "Student")
public class Student {
#EmbeddableId
private StudentPK itemId;
#Column(name="StudentName")
private String studentName;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name="Student_Teacher", joinColumns={#JoinColumn(name="SchoolId", referencedColumnName="SchoolId"),#JoinColumn(name="StudentId", referencedColumnName="StudentId")}, inverseJoinColumns={#JoinColumn(name="SchoolId", referencedColumnName="SchoolId"),#JoinColumn(name="TeacherId", referencedColumnName="TeacherId")})
private List<Teacher> attachments=new ArrayList<Teacher>();
}
The above code compains about some duplicate SchoolId reference.
Any ideas?
As I see that there is an issue in your mapping of entities, It should be as follows
school - school_id(PK), school_name
student - student_id(PK) , student_name, fk_school_id(FK),
teacher - teacher_id(PK), teacher_name , fk_school_id(FK)
*student_teacher* - student_teacher_id(PK), fk_student_id(FK), fk_teacher_id(FK)
and Entity clasess as follows
School Entity
#Entity
#Table(name = "school")
public class School {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column (name = "school_id")
private int Id;
#Column(name="school_name")
private String schoolName;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "school")
private Set<Student> students = new HashSet<Student>
#OneToMany(fetch = FetchType.LAZY, mappedBy = "school")
private Set<Teacher> teachers = new HashSet<Teacher>
}
Student Entity
#Entity
#Table(name = "student")
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column (name = "student_id")
private int Id;
#Column(name="student_name")
private String studentName;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "school_id", nullable = false)
private School school;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "student_teacher", joinColumns = {#JoinColumn(name = "fk_student_id") }, inverseJoinColumns = { #JoinColumn(name = "fk_teacher_id") })
private List<Teacher> teachers = new ArrayList<Teacher>();
}
Teacher Entity
#Entity
#Table(name = "teacher")
public class Teacher {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column (name = "teacher_id")
private int Id;
#Column(name="teacher_name")
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "school_id", nullable = false)
private School school;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "student_teacher", joinColumns = {#JoinColumn(name = "fk_teacher_id") }, inverseJoinColumns = { #JoinColumn(name = "fk_student_id") })
private List<Student> students =new ArrayList<Student>();
}
hope this will solve this problem..
as you have declare 'SchoolId' as PK in Student_Teacher table it will not allow you to add duplicate entry for SchoolId field for Student_Teacher table and this is not the case. thus the above relationship will gives duplicate SchoolId reference. when you are going to add two different students from same school into Student_Teacher table..
Did you define the various PKs per entity as compound keys, as i note that you use multiple PKs per entity. Is there any constraint why you can't use a sole PK per entity and just use a relation table to bind the 2 entities?