I have a table that holds events where the data is stored as a JSON object.
What i'am trying to do is have different entities mapped to the same table, because some of these events need to join with other tables to be useful.
What i tried doing:
EntityA is the "default" entity for the table, all events are received in this entity an them stored.
#Entity(name = "entity_a")
#Table(name = "table_a")
public class EntityA {
#Id
private UUID id;
#Column(name = "fielda")
private String fieldA;
#Column(name = "fieldb")
private Integer fieldB;
#Column(name = "json_field")
private Object jsonField;
}
EntityAB is a map of the same table with a new field that is a join with another table.
#Entity(name = "entity_ab")
#Table(name = "table_a")
public class EntityAB {
#Id
private UUID id;
#Column(name = "fielda")
private String fieldA;
#Column(name = "fieldb")
private Integer fieldB;
#Column(name = "json_field")
private Object jsonField;
#ManyToOne
#ManyToOne
#JoinColumnsOrFormulas(value = {
#JoinColumnOrFormula(formula = #JoinFormula(value = "JSON_VALUE(jsonField, '$.field_id_a')", referencedColumnName = "field_id_a")),
#JoinColumnOrFormula(formula = #JoinFormula(value = "JSON_VALUE(jsonField, '$.field_id_b')", referencedColumnName = "field_id_b")),
#JoinColumnOrFormula(formula = #JoinFormula(value = "JSON_VALUE(jsonField, '$.fieldc')", referencedColumnName = "fieldc")),
})
private EntityB entityB;
}
EntityB is used in the EntityAB.
public class EntityB implements Serializable {
#EmbeddedId
private EntityBId id;
#Column(name = "fieldc")
private String fieldC;
}
#Embeddable
public class EntityBId implements Serializable {
#Column(name = "field_id_a")
private String fieldIdA;
#Column(name = "field_id_b")
private Integer fieldIdB;
#Column(name = "field_id_c")
private Integer fieldIdC;
}
When starting the application, it gives me this error:
referencedColumnNames(field_id_a, field_id_b, fieldc) of EntityAB.entityB referencing EntityB not mapped to a single property
If i dont use the fields "field_id_a" and "field_id_b" (EmbeddedId) in the join, it works, but it's not the right join. From what i have searched it looks like i can't have a parcial PK join when using "EmbeddedId", is that correct?
Related
I have the following entities in a Hibernate - Spring proyect.
Member:
#Entity
#Table(name = "member")
public class Member implements Serializable {
private static final long serialVersionUID = 1871629487715861212L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "ident_doc")
private String identDoc;
#Column(name = "join_date")
private String joinDate;
private String nickname;
#OneToOne(mappedBy = "member")
private MemberContact memberContact;
#OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberChapterLog> memberChapterLogs;
#OneToMany(mappedBy = "member")
private List<ChapterOfficers> chapterOfficers;
#OneToOne(mappedBy = "contactMember", cascade = CascadeType.ALL)
private Chapter asChapterContact;
Chapter:
#Entity
#Table(name = "chapter")
#NamedQuery(
name = "Chapter_Get_Detailed_Members_List",
query = "from MemberChapterLog where chapter.id = :paramChapter and active = true "+
"order by member.lastName asc")
public class Chapter implements Serializable {
private static final long serialVersionUID = -8387387246818721664L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String initials;
#Column(name ="chap_name")
private String chapName;
#ManyToOne
#JoinColumn(name = "category")
private ChapCategory category;
#OneToOne
#JoinColumn(name = "contact_member")
private Member contactMember;
#OneToOne(mappedBy = "chapter", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private ChapterContact chapterContact;
#OneToMany(mappedBy = "chapter")
private List<MemberChapterLog> memberChapterlogs;
#OneToMany(mappedBy = "chapter")
private List<ChapterOfficers> chapterOfficers;
MemberChapterLog:
#Entity
#Table(name = "member_chapter_log")
public class MemberChapterLog implements Serializable {
private static final long serialVersionUID = -643503606583240644L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "member_id")
private Member member;
#ManyToOne
#JoinColumn(name = "chapter_id")
private Chapter chapter;
#Column(name = "log_date")
private String logDate;
private String comment;
private boolean active;
I want to get a list of the active members of certain chapter (passed as ':paramChapter'), order by their last name. When I run the named query at chapter ("from MemberChapterLog where chapter.id = :paramChapter and active = true order by member.lastName asc") it generates the following error:
org.hibernate.HibernateException: Errors in named queries:
Chapter_Get_Detailed_Members_List failed because of: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: member near line 1, column 105 [from dev.xarlsr.cdt.entity.MemberChapterLog where chapter.id = :paramChapter and active = true order by member.lastName asc]
If I delete the order by member.lastName it works properly (without any order, byt the way).
I tried to change the mapping by changing the tables foreign keys and the ownership, but doesn't work. I tried to change the fetch type without results. What am I doing wrong?
The problem is the mapping:
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "member_id")
private Member member;
member is a keyword in JPQL/HQL and soft-keyword handling was only introduced in Hibernate 6, so you will need to change the name of the field to e.g. memberAssociation and the query condition to ... order by memberAssociation.lastName asc
In my spring boot project, I have one LineItem entity below is the code
#Entity
#Table(name = "scenario_lineitem")
#Data
#NoArgsConstructor
public class LineItem implements Cloneable {
private static Logger logger = LoggerFactory.getLogger(GoogleConfigConstant.class);
#Id
#GeneratedValue(strategy = IDENTITY)
private BigInteger lineItemId;
#Column
private String name;
#OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL, CascadeType.PERSIST, CascadeType.MERGE })
#JoinColumn(name = "line_item_meta_id")
private List<QuickPopValue> quickPopValues;
}
Another entity is
#Entity
#Table(name = "quick_pop_value")
#Data
#NoArgsConstructor
public class QuickPopValue implements Cloneable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "quick_pop_value_id", columnDefinition = "bigint(20)", unique = true, nullable = false)
private BigInteger quickPopValueId;
#Column(name = "column_name")
private String columnName;
#Column(name = "value")
private String value;
#Column(name = "formula", columnDefinition = "longtext")
private String formula;
}
Now I am trying to delete QuickPopValue one by one but it's not getting deleted and not getting any exception as well.
Below is the delete code :
List<QuickPopValue> quickPopValues = sheetRepository.findByColumnName(columnName);
for (QuickPopValue qpValue : quickPopValues) {
quickPopValueRepository.delete(qpValue);
}
Such behavior occurs when deleted object persisted in the current session.
for (QuickPopValue qpValue : quickPopValues) {
// Here you delete qpValue but this object persisted in `quickPopValues` array which is
quickPopValueRepository.delete(qpValue);
}
To solve this you can try delete by id
#Modifying
#Query("delete from QuickPopValue t where t.quickPopValueId = ?1")
void deleteQuickPopValue(Long entityId);
for (QuickPopValue qpValue : quickPopValues) {
quickPopValueRepository.deleteQuickPopValue(qpValue.getQuickPopValueId());
}
I want to join only one column from another table.
I have 2 entities now:
#Entity
public class Message {
....
#ManyToOne
#JoinColumn(name = "ATTRIBUTE_ID")
private Attribute attribute;
}
#Entity
#Table(name = "ATTRIBUTE_TABLE")
public class Attribute {
#Id
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
}
And I want to simplify code and don't use entity for only one column:
#Entity
#SecondaryTable(name = "ATTRIBUTE_TABLE", pkJoinColumns =
#PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "ATTRIBUTE_ID")),
public class Message {
....
#Column(table = "ATTRIBUTE_TABLE", name = "NAME")
private String attribute;
}
But #SecondaryTable JoinColumn cannot reference a non-primary key.
How to add a column from another table without using additional entity for it?
I am not so into Spring Data JPA and I have the following problem trying to implement a named query (the query defined by the method name).
I have these 3 entity classes:
#Entity
#Table(name = "room_tipology")
public class RoomTipology implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "tipology_name")
private String name;
#Column(name = "tipology_description")
private String description;
#Column(name = "time_stamp")
private Date timeStamp;
#OneToMany(mappedBy = "roomTipology")
private List<Room> rooms;
#OneToOne(mappedBy = "roomTipology")
private RoomRate roomRate;
// GETTER AND SETTER METHODS
}
That represents a tipology of room and that contains this field
#OneToMany(mappedBy = "roomTipology")
private List<Room> rooms;
So it contains the list of room associated to a specific room tipology, so I have this Room entity class:
#Entity
#Table(name = "room")
public class Room implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#ManyToOne
#JoinColumn(name = "id_accomodation_fk", nullable = false)
private Accomodation accomodation;
#ManyToOne
#JoinColumn(name = "id_room_tipology_fk", nullable = false)
private RoomTipology roomTipology;
#Column(name = "room_number")
private String number;
#Column(name = "room_name")
private String name;
#Column(name = "room_description")
#Type(type="text")
private String description;
#Column(name = "max_people")
private Integer maxPeople;
#Column(name = "is_enabled")
private Boolean isEnabled;
// GETTER AND SETTER METHODS
}
Representing a room of an accomodation, it contains this annoted field:
#ManyToOne
#JoinColumn(name = "id_accomodation_fk", nullable = false)
private Accomodation accomodation;
And finally the Accomodation entity class:
#Entity
#Table(name = "accomodation")
public class Accomodation implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#OneToMany(mappedBy = "accomodation")
private List<Room> rooms;
#Column(name = "accomodation_name")
private String name;
#Column(name = "description")
#Type(type="text")
private String description;
// GETTER AND SETTER METHODS
}
Ok, so now I have this Spring Data JPA repository class for RoomTipology:
#Repository
#Transactional(propagation = Propagation.MANDATORY)
public interface RoomTipologyDAO extends JpaRepository<RoomTipology, Long> {
}
Here I want to define a named query method that return to me the list of all the RoomTipology object related to a specific accomodation, I have done it using SQL and it works fine:
SELECT *
FROM room_tipology as rt
JOIN room r
ON rt.id = r.id_room_tipology_fk
JOIN accomodation a
ON r.id_accomodation_fk = a.id
WHERE a.id = 7
But now I want to translate it in a named query method (or at least using HQL)
How can I do it?
Please Try:
#Repository
#Transactional(propagation = Propagation.MANDATORY)
public interface RoomTipologyDAO extends JpaRepository<RoomTipology, Long> {
List<RoomTipology> findByRooms_Accomodation(Accomodation accomodation);
}
The query builder mechanism built into Spring Data repository infrastructure is useful for building constraining queries over entities of the repository. The mechanism strips the prefixes find…By, read…By, query…By, count…By, and get…By from the method and starts parsing the rest of it
At query creation time you already make sure that the parsed property is a property of the managed domain class. However, you can also define constraints by traversing nested properties.
Doc:Here
I am trying to use hibernate to retrieve data from my database...I have a query that joins two tables (all fields being one to one) using a left join. I need to know how to handle this with hibernate and annotations. I have created two classes that map to tables and I am trying to figure out how to use the joins...Hibernate docs are confusing...
//one class
#Entity
#Table(name = "Class1")
public class Class1{
#Id
#Column(name = "INITIAL")
private String initial;
#Column(name = "NUMBER")
private Integer number;
...
//twoclass
#Entity
#Table(name = "Class2")
public class Class2{
#Column(name = "STATE")
private String state;
#Id
#Column(name = "NUMBER")
private Integer number
...
#Entity
#Table(name = "Class1")
public class Class1 {
#Id
#Column(name = "INITIAL")
private String initial;
#Column(name = "NUMBER")
private Integer number;
}
#Entity
#Table(name = "Class2")
public class Class2 {
#Id
#Column(name = "STATE")
private String state;
#Column(name = "NUMBER")
private Integer number
#OneToOne
#JoinColumn(name = "columnWithClass1id")
private Class1 class1;
}