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?
Related
#OneToMany side of the relation populates well but the #ManyToOne side overrides each time(only the last item persists)
#Entity
#Table(name="order")
public class Order {
#Id
#Column(name ="orderId")
private String orderId;
#OneToMany(targetEntity = Items.class,
fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "orderId")
#NotNull
private Set<Items> items;
.......
}
#Entity
public class Items {
#Id
private String itemId;
#ManyToOne
#JoinColumn(name="orderId",referencedColumnName = "orderId")
private Order order;
............
}
#Entity
#Table(name="order")
public class Order {
#Id
#Column(name ="orderId")
private String orderId;
#OneToMany(targetEntity = Items.class,
fetch = FetchType.EAGER, cascade = CascadeType.ALL
,mappedBy = "item_id")
#NotNull
private Set<Items> items;
.......
}
#Entity
public class Items {
#Id
private String itemId;
#ManyToOne
#JoinColumn(name="orderId",referencedColumnName = "orderId")
private Order order;
............
Replace targetEntity = Items.class by mappedBy = "order"
and remove referencedColumnName = "orderId" and #JoinColumn(name = "orderId") from OneToMany.
Also if you really need eager fetching delete it from OneToMany side - ManyToOne is eager by default.
Running a project with the following classes fails with:
org.hibernate.MappingException: Foreign key
(FK9ex9b0501jh788ukls6wuglix:a_bc [bc_id])) must have same number of
columns as the referenced primary key (bc [b_id,c_id])
#Entity
public class A {
#Id
private Long id;
#ManyToMany
#JoinTable(name = "A_BC",
joinColumns = #JoinColumn(name = "A_ID"),
inverseJoinColumns = #JoinColumn(name = "BC_ID"))
private Set<BC> set;
}
#Entity
public class B {
#Id
private Long id;
#ManyToMany
#JoinTable(name = "BC",
joinColumns = #JoinColumn(name = "B_ID"),
inverseJoinColumns = #JoinColumn(name = "C_ID"))
private Set<C> set;
}
#Entity
public class C {
#Id
private Long id;
#ManyToMany
#JoinTable(name = "BC",
joinColumns = #JoinColumn(name = "C_ID"),
inverseJoinColumns = #JoinColumn(name = "B_ID"))
private Set<B> set;
}
#Entity
public class BC {
#Id
private Long id;
#ManyToOne
#JoinColumn(name = "B_ID")
private B b;
#ManyToOne
#JoinColumn(name = "C_ID")
private C c;
#ManyToMany
#JoinTable(name = "A_BC",
joinColumns = #JoinColumn(name = "BC_ID"),
inverseJoinColumns = #JoinColumn(name = "A_ID"))
private Set<A> set;
}
#Entity
public class A_BC {
#Id
private Long id;
#ManyToOne
#JoinColumn(name = "A_ID")
private A a;
#ManyToOne
#JoinColumn(name = "BC_ID")
private BC bc;
}
Entities B, C and BC work as expected. B and C are connected to one another using BC as a join table.
The problem arises when introducing the entity A and asociating it with BC. BC acts as a join table but it's also a part of another join table (A_BC), I think this is what is causing the error, but I don't see why or how to fix it.
The issue is that you have a #OneToMany on one side and #ManyToMany on the other.
I'm trying to use Spring Data to perform joined queries but one of my tables has a Composite Key and I'm not sure how to map the entities.
Here is an analogy of the data model:
table: device
pk=model_id
pk=serial_id
...
table: device_settings
pk=device_settings_id
fk=model_id
fk=serial_id
...
Here is an analogy of the code, which doesn't compile due to a "mappedby" attribute that is isn't present.
#Entity
#Table(name = "device_settings")
public class DeviceSettings {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "device_settings_id")
private Long id;
// Pretty sure this is the problem
#OneToMany(targetEntity = Device.class, mappedBy = "deviceKey", cascade = {CascadeType.MERGE}, fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "model_id", referencedColumnName = "model_id"),
#JoinColumn(name = "serial_id", referencedColumnName = "serial_id")})
private List<Device> devices;
}
#Entity
#Table(name = "device")
public class Device {
#Id
private DeviceKey deviceKey;
}
...
}
#Embeddable
public class DeviceKey implements Serializable {
private static final long serialVersionUID = -1943684511893963184L;
#Column(name = "model_id")
private Long modelId;
#Column(name = "serial_id")
private Short serialId;
}
Associations marked as mappedBy must not define database mappings like #JoinTable or #JoinColumn
To achieve your scenario you have to define #ManyToOne:
#ManyToOne(cascade = {CascadeType.MERGE}, fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "model_id", referencedColumnName = "model_id"),
#JoinColumn(name = "serial_id", referencedColumnName = "serial_id")})
private Device device;
This will end up model_id, serial_id, device_settings_id
or
Define #JoinColumn in Device Entity
Entities:
DeviceSettings :
#Entity
#Table(name = "device_settings")
public class DeviceSettings {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "device_settings_id")
private Long id;
#OneToMany( mappedBy = "deviceSettings", cascade = {CascadeType.MERGE}, fetch = FetchType.EAGER)
private List<Device> devices;
}
Device Entity :
#Entity
#Table(name = "device")
public class Device {
#EmbeddedId
private DeviceKey deviceKey;
#ManyToOne
#JoinColumn(name="device_settings_id")
private DeviceSettings deviceSettings;
//getters and setters
}
Note : you can decide which is the owner of the relationship and put your mappings accorindly either One Device has many device settings or other way around.
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;
...
}
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;