Reputation: 1424
I have a problem to handle mapping object relationship for mysql tables. I have 2 tables shown below:
Device
-----------
deviceId PK
deviceName
ApkInfo
--------
id PK
packageName
appName
deviceId FK
And then here are my classes:
@Entity
@Table(name="Device")
public class Device implements Serializable {
@Column
@Id
private String deviceId;
@Column
private String deviceName;
//getters and setters
}
@Entity
@Table(name="ApkInfos")
public class ApkInfo implements Serializable {
@Column
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column
@Id
private String packageName;
@Column
private String appName;
@Column
@Temporal(TemporalType.TIMSTAMP)
private Date installDate;
@ManyToOne
@JoinColumn(name="deviceId" referencedColumnName="deviceId")
private Device device;
//getters and setters
}
This works for me, but I want to use compound key, deviceId
and packageName
, in ApkInfos
table.
@Entity
@Table(name="ApkInfos")
public class ApkInfo implements Serializable {
@Colum(instable=false, updatable=false)
@Id
private String deviceId;
@Column
private String packageName;
@Column
private String appName;
@ManyToOne
@JoinColumn(name="deviceId" referencedColumnName="deviceId")
private Device device;
//getters and setters
}
But when I tried to save an entity using Spring Data JPA repository, I got an error:
org.springframework.dao.InvalidAccessApiUsageException: Class must not be null, nested exception is java.lang.IllegalArgumentException: Class must not be null
ApkInfo apkInfo = new ApkInfo();
apkInfo.setDeviceId("1234");
apkInfo.setPackageName("aaa");
apkInfo.setAppName("myapp");
apkInfo.setInstallDate(new Date());
apkInfo.setDevice(new Device("1234"));
repository.save(apkInfo);
And device has the deviceID
'1234' already exists in the Device table.
Upvotes: 3
Views: 8435
Reputation: 1424
I created a separate primary key class added @IdClass in the ApkInfo class. It works fine now, thanks. I am going to have a look at EmbeddedId more later.
I added @IdClass at the entity class and @Id for the packageName property. Also I made insert, update false for the One-to-many column.
@Entity
@Table(name="ApkInfos")
@IdClass(ApkInfo.class)
public class ApkInfo implements Serializable {
@Column @Id private String deviceId;
@Column @Id private String packageName;
@ManyToOne
@JoinColumn(name="deviceId" referencedColumnName="deviceId", insetable=false, updatable=false)
private Device device;
//getters and setters missing
}
Primary key class has only setters and overrides equals and hasCode methods.
public class ApkInfo implements Serializable {
private String deviceId;
private String packageName;
public ApkInfo(){}
public ApkInfo (String deviceId, String packageName){
this.deviceId = deviceId;
this.packageName = packageName;
}
public String getDeviceId(){
return this.deviceId;
}
public String getPackageName(){
return this.packageName;
}
@Override
public boolean equals(Object obj){
return (obj!=null &&
obj instanceof ApkInfoPk &&
deviceId.equals(((ApkInfoPk)obj).getDeviceId()) &&
packageNames.equals(((ApkInfoPk)obj).getPackageName()) );
}
@Override
public int hashCode(){
super.hashCode();
}
}
Upvotes: 6