如何在JPA2和Spring Data JPA中处理具有关系的复合键?

时间:2013-05-06 01:55:37

标签: jpa spring-data-jpa

我有一个问题来处理mysql表的映射对象关系。 我有2个表格如下所示:

Device
-----------
deviceId PK
deviceName

ApkInfo
--------
id PK
packageName
appName
deviceId FK

然后这是我的课程:

@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

}

这对我有用,但我想在deviceId表中使用复合键packageNameApkInfos

@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

}

但是当我尝试使用Spring Data JPA存储库保存实体时,我收到了一个错误:

  

org.springframework.dao.InvalidAccessApiUsageException:类不能   为null,嵌套异常为java.lang.IllegalArgumentException:Class   不能为空

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);

设备表格中已存在deviceID'1234'。

1 个答案:

答案 0 :(得分:5)

我在ApkInfo类中创建了一个单独的主键类@IdClass。它现在工作正常,谢谢。我稍后会看看EmbeddedId。

我在实体类中添加了@IdClass,在packageName属性中添加了@Id。此外,我为一对多列进行了插入,更新为false。

@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
}

主键类只有setter并覆盖equals和hasCode方法。

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();
   }
}