The following mapping is giving an error of
A Foreign key refering db.KarateInvoice from db.KarateInvoiceDetail
has the wrong number of column. should be 1
Invoice Entity:
#Id
#Column(name = "id")
private long id;
#OneToOne
#JoinColumn(name = "companyid")
#Id
private Company company;
#Id
private short fiscalYear;
#OneToMany(mappedBy = "karateInvoiceDetails")
private List<KarateInvoiceDetail> karateInvoiceDetails;
Invoice Detail:
#Id
private short seqNo;
#ManyToOne
#JoinColumns({ #JoinColumn(name = "karateInvoiceId"),
#JoinColumn(name = "karateInvoiceCompanyId"),
#JoinColumn(name = "karateInvoiceFiscalYear") })
private KarateInvoice invoice;
#Id
#OneToOne
#JoinColumns({ #JoinColumn(name = "studentId"),
#JoinColumn(name = "studentCompanyId") })
private KarateStudent student;
Company Entity:
#Id
private long id;
Idea is to have an Invoice table with a composite of (id, fiscalyear, and companyId) and InvoiceDetail with a composite key of (seqNo, InvoiceId, InvoiceFiscalYear, and InvoiceCompanyId).
I think you should explicitly reference the Invoice columns on the #JoinColumn annotations:
#ManyToOne
#JoinColumns({ #JoinColumn(name = "karateInvoiceId"
, referencedColumnName="id"),
#JoinColumn(name = "karateInvoiceCompanyId"
, referencedColumnName="companyId"),
#JoinColumn(name = "karateInvoiceFiscalYear"
, referencedColumnName="fiscalYear") })
private KarateInvoice invoice;
Related
Consider the following database structure
I need to implement unidirectional one to one mapping like that (structure is simplified):
#Entity
#Table(name = "entity")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#OneToOne
#JoinColumn(name = "customer_info", nullable = false)
private CustomerInfo customerInfo;
#OneToOne
#JoinColumn(name = "customer_credentials", nullable = false)
private CustomerCredentials customerCredentials;
// getter, setters etc
}
#Entity
#Table(name = "customer_info")
public class CustomerInfo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
// getter, setters etc
}
#Entity
#Table(name = "customer_credentials")
public class CustomerCredentials {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
// getter, setters etc
}
But somehow hibernate unable to differentiate that those joins are from different tables and throws such error:
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.example.Customer column: customer_id (should be mapped with insert="false" update="false")
Important notice: I do not want to use #OneToOne(mappedBy = "customer") because I need cascade save functionality
You can use #JoinTable instead of #JoinColumn to solve your problem:
#Entity #Table(name = "entity") public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#OneToOne(cascade = CascadeType.ALL, targetEntity = CustomerInfo.class)
#JoinTable(name = "customer_info", inverseJoinColumns = {#JoinColumn(name = "customer_id", nullable = false)})
private CustomerInfo customerInfo;
#OneToOne(cascade = CascadeType.ALL, targetEntity = CustomerCredentials.class)
#JoinTable(name = "customer_credentials", inverseJoinColumns = {#JoinColumn(name = "customer_id", nullable = false)})
private CustomerCredentials customerCredentials;
// getter, setters etc }
#Entity #Table(name = "customer_info") public class CustomerInfo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
// getter, setters etc }
#Entity #Table(name = "customer_credentials") public class CustomerCredentials {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
// getter, setters etc }
You could change the cascade strategy to any strategy you need. I just left CascadeType.ALL there as an example.
There is a table ORDERS from which were created views ORDER_VIEW_A and ORDER_VIEW_B.
I have created entity classes OrderViewA and OrderViewB where in each of them is mapping on entity named 'TransactionRecord'.
It is #OneToOne relationship.
There is column ORDER_ID in TRANSACTION_RECORD table and field orderId in TransactionRecord entity.
Field orderId is same for OrderViewA.id and for OrderViewB.id, cause views are selected from the same table.
My question is, how to map in Hibernate two views in OneToOne relationship with another entity by same field.
My code looks like this and it doesn't work in any way, Hibernate always end up with:
org.hibernate.AnnotationException: Referenced property not a
(One|Many)ToOne: com.example.app.model.TransactionRecord.orderId in
mappedBy of com.example.app.model.views.OrderViewA.orderViewA
#Entity
#Immutable
#Table(name = "ORDER_VIEW_A")
public class OrderViewA {
#Id
#Column(name = "id")
private Long id;
...
#OneToOne(mappedBy = "orderId", fetch = FetchType.LAZY)
private IntegrationRecord orderARecord;
...
}
#Entity
#Immutable
#Table(name = "ORDER_VIEW_B")
public class OrderViewB {
#Id
#Column(name = "id")
private Long id;
...
#OneToOne(mappedBy = "orderId", fetch = FetchType.LAZY)
private IntegrationRecord orderBRecord;
...
}
#Entity
#Table(name = "TRANSACTION_RECORD")
public class TransactionRecord {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "order_id")
private Long orderId;
...
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "order_id")
private OrderViewA orderViewA;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "order_id")
private OrderViewB orderViewB;
...
}
The Console Error: A Foreign key refering com.api.subscriber.pojo.MapperSubscriberTracker from com.api.tracker.pojo.Tracker has the wrong number of column. should be 2
public class MapperSubscriberTracker implements Serializable {
#Id
#Column(name = "tracker_id")
private int trackerID;
#ManyToOne
#Id
#JoinColumn(name = "subscriber_id")
#JsonBackReference
private Subscriber subscriber;
#OneToMany(fetch = FetchType.EAGER,mappedBy = "mapperSubscriberTracker", cascade = CascadeType.ALL)
#JsonManagedReference
private Set<Tracker> trackers;
...
}
public class Tracker {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#ManyToOne
#JoinColumn(name = "subscriber_id")
#JsonBackReference
private MapperSubscriberTracker mapperSubscriberTracker;
...
}
I've also tried the following method with the same error:
B {
#ManyToOne
#JoinColumn(name = "b3", referencedColumnName = "a3")
privte A a;
}
A {
#OneToMany
#JoinColumn(name = "a3", referencedColumnName = "b3")
privte List<B> bList;
}
I understand it wants 2 keys to join on because of the composite key but I don't want to do that. Is there a way to force it to join on the one column?
I have two classes that have 2 relations between them.
User class:
#Entity
#Table(name="User")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="Id")
private long id;
#OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="admin")
private Set<Group> ownedGroup;
#ManyToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="members")
private Set<Group> memberGroups;
//.......
}
Group class:
#Entity
#Table(name="Group")
public class Group implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="Id")
private long id;
#NotNull
#ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="Admin", referencedColumnName="Id")
private User admin;
#ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinTable(name = "Group_User",
joinColumns = #JoinColumn(name = "Group"),
inverseJoinColumns = #JoinColumn(name = "User"))
private Set<User> members;
//....
}
When I want to start the App, I get this exception:
org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.myproject.model.User.memberGroups[com.querydsl.core.group.Group]
I saw other similar posts, but apparently they didn't use javax.persistence.Entity and it was the root cause of this error. Any idea how to resolve this issue ?
Group is a reserved keyword. Use backtick to escape a reserved keyword. Check out this answer.
#Table(name = "`Group`")
Also your #ManyToMany mapping is unfortunately not correct.
Update your Group entity like so :
#Entity
#Table(name="`Group`") // Change your table name
public class Group implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="Id")
private long id;
#NotNull
#ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="Admin", referencedColumnName="Id")
private User admin;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "Group_User",
joinColumns = #JoinColumn(name = "group_id", referencedColumnName = "id"), //Give a column name 'group_id' and map it to Group primary key id
inverseJoinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id") //Give a column name 'user_id' and map it to User primary key id.
)
private Set<User> members;
...
}
I have three entities. The first one is Company entity (see below).
#Entity
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column
private String name;
#JoinColumn(name = "company_id")
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Employee> employees;
#OneToMany(mappedBy = "company")
private List<HistoryRecord> historyRecords;
The second is Employee
#Entity
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Integer id;
#Column
String name;
#ManyToOne
#JoinColumn(name = "company_id", nullable = true)
private Company company;
#OneToMany(mappedBy = "employee")
private List<HistoryRecord> historyRecords;
Here is my HistoryRecord class
#Entity
public class HistoryRecord {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Integer id;
#ManyToOne
#JoinColumn(name = "company_id")
Employee employee;
#ManyToOne
#JoinColumn(name = "employee_id")
Company company;
#Column(name = "hire_date")
Date hireDate;
#Column(name = "resign_date")
Date resignDate;
When I'm trying to execute delete operation on Employee I'm getting this error
HTTP Status 500 - Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; SQL [delete from employee where id=?]; constraint ["CONSTRAINT_12: PUBLIC.HISTORY_RECORD FOREIGN KEY(EMPLOYEE_ID) REFERENCES PUBLIC.EMPLOYEE(ID)
I think the problem is in cascade operation but I'm not sure. Is anybody can say how can I fix it?
The problem is due to the relationship of Employee -- HistoryRecord. The employee property on HistoryRecord is not nullable. If you want the HistoryRecord to be deleted when an employee is being deleted you need to add the cascade attribute to the #OneToMany(mappedBy = "employee") for historyRecords on Employee.
#OneToMany(mappedBy = "employee",cascade = CascadeType.REMOVE)
The ENDDM generates
ALTER TABLE "public"."project_group" ADD CONSTRAINT "mandant" FOREIGN KEY (mandant_id) REFERENCES "mandant" ("mandant_id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
for the database and
#OneToMany(cascade = CascadeType.REMOVE)
in Java.
Update your relation mapping in Company class is is missing cascade.
#OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
private List<HistoryRecord> historyRecords;