Spring Join Single Column of a Composite Key - java

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

ManyToOne not persisted

#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.

Receiving Error "Foreign key must have same number of columns as the referenced primary key" despite not using composite keys

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.

Hibernate Composite Key Join

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.

Exception thrown when having multiple relations between two entities

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;
...
}

Many to One Mapping in Hibernate

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;

Categories

Resources