2016-03-31 20 views
1

私のデバイス用のデータを取得するためにJPA Entity Beanを構築する方法を理解しようとしています。データベースは古くて石であるので、スキーマを変更することはできません。デバイスモデルには複合主キーがあり、列の1つはFKからデバイスタイプです。主キーの一部が外部キーであるJPAでの複合主キーのマッピング方法

私はいくつかのことを試しました。まずDeviceにDeviceModelとDeviceTypeがありましたが、dev_typeを参照しているものが多すぎるというエラーが表示されました。そこでDeviceModelにDeviceTypeへの参照を持たせようとしましたが、同じエラーが発生しました。

私が役立つならば、Spring Data 4.2.xとHibernate 4.3.8.Finalを使用してすべてを戻します。

私がオンラインで見つけたその他の回答(How to create and handle composite primary key in JPAなど)は、基本的なデータ型にのみ対応しているため、助けにはなりません。実際、上記の答えは私のコードで実装されています...しかし、私はさらに1レベル進む必要があります。

スキーマ:(それは私が助けを必要とするものだが、デバイスまたはデバイスモデルのいずれかにDeviceTypeをネクタイしていない)、これまで

create table devices 
(
    device_nbr serial(1), 
    device_id nchar(20) not null unique, 
    dev_type integer not null, 
    model_nbr integer default 1, 
    unit_addr nchar(32), 
    primary key (device_nbr), 
    foreign key (dev_type) references devtypes (dev_type), 
    foreign key (dev_type, model_nbr) references devmodels (dev_type, model_nbr) 
); 

create table devmodels 
(
    dev_type  integer not null, 
    model_nbr  integer not null, 
    model_desc nchar(20), 
    primary key (dev_type, model_nbr), 
    foreign key (dev_type) references devtypes (dev_type) 
); 

create table devtypes 
(
    dev_type integer not null, 
    dev_desc nchar(16) not null unique, 
    primary key (dev_type) 
); 

マイビーンズ:

@Entity 
@Table(name = "devices") 
public class Device 
{ 
    @Id 
    @GeneratedValue 
    @Column(name = "device_nbr") 
    private Long    number; 

    @Column(name = "device_id", length = 30) 
    private String   id; 

    @Column(name = "unit_addr", length = 30) 
    private String   unitAddress; 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumns({ 
     @JoinColumn(name = "dev_type"), 
     @JoinColumn(name = "model_nbr") 
    }) 
    private DeviceModel deviceModel; 

...Getters and setters 
} 

public class DeviceModelPK implements Serializable 
{ 
    private static final long serialVersionUID = -8173857210615808268L; 
    protected Integer     deviceTypeNumber; 
    protected Integer     modelNumber; 

...Getters and setters 
} 

@Entity 
@Table(name = "devmodels") 
@IdClass(DeviceModelPK.class) 
public class DeviceModel 
{ 
    @Id 
    @Column(name = "dev_type") 
    private Integer   deviceTypeNumber; 

    @Id 
    @Column(name = "model_nbr") 
    private Integer   modelNumber; 

    @Column(name = "model_desc") 
    private String   description; 

...Getters and setters 
} 

@Entity 
@Table(name = "devtypes") 
public class DeviceType 
{ 
    @Id 
    @GeneratedValue 
    @Column(name = "dev_type") 
    private Integer number; 

    @Column(name = "dev_desc", length = 30) 
    private String description; 

...Getters and setters 
} 
+2

可能性のある重複した[作成し、JPAで複合主キーを処理する方法](http://stackoverflow.com/questions/13032948/how-to-create-and-handle-composite-primary-key- in-jpa) –

+0

'@ IdClass'の代わりに' @ EmbeddedId'を試してみませんか? '彼らは基本的なデータ型にのみマップするので'あなたはこれについてのリファレンスを見つけましたか? –

+0

私は '@ EmbeddedId'を試していませんが、同じ列を参照する2つの異なるJavaフィールドの問題をどのように解決するかはわかりません。 –

答えて

2

まあ、基本的な問題はエンティティの代わりに列の観点から考えていますが、それは難しい問題なので不公平なステートメントかもしれません。基本的な質問は、エンティティをコンポジットキーの一部として含める方法です。答えは、How to create a composite primary key which contains a @ManyToOne attribute as an @EmbeddedId in JPA?です。 デバイス:

@Entity 
@Table(name = "devices") 
public class Device 
{ 
    @Id 
    @Column(name = "device_nbr") 
    private Long number; 

    @Column(name = "device_id", length = 20) 
    private String deviceId; 

    @ManyToOne(fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
    @JoinColumns({@JoinColumn(name="dev_type", referencedColumnName="dev_type"), @JoinColumn(name="model_nbr", referencedColumnName="model_nbr")}) 
    private DeviceModel deviceModel; 

    // This creates a foreign key constraint, but otherwise doesn't function 
    // deviceType must be accessed through deviceModel 
    // note, it can be used for explicit selects, e.g., "select d.deviceType from Device d" 
    @OneToOne(fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
    @JoinColumn(name="dev_type", referencedColumnName="dev_type", insertable=false, updatable=false) 
    private DeviceType deviceType; 

    @Column(name = "unit_addr", length = 32) 
    private String unitAddress; 

デバイスモデル:

@Entity 
@Table(name = "devmodels") 
public class DeviceModel 
{ 
    @EmbeddedId 
    private DeviceModelId id; 

    @ManyToOne(fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
    @JoinColumn(name="dev_type") 
    @MapsId("deviceType") 
    private DeviceType deviceType; 

    @Column(name = "model_desc", length=20) 
    private String description; 

DeviceModelId:私は@Embeddable@EmbeddedIdを使用

@Embeddable 
public class DeviceModelId implements Serializable 
{ 
    private static final long serialVersionUID = -8173857210615808268L; 
    private Integer deviceType; 
    @Column(name="model_nbr") 
    private Integer modelNumber; 

注意してください。それはちょうど新しいと私は@IdClassより優先されるJPAプロバイダのコメントを読んだ。私はそれも列の名前を少し簡単にしたと思うが、私は覚えていない。

DeviceTypeを:

@Entity 
@Table(name = "devtypes") 
public class DeviceType 
{ 
    @Id 
    @GeneratedValue 
    @Column(name = "dev_type") 
    private Integer deviceType; 

    @Column(name = "dev_desc", length = 16) 
    private String description; 

トリックはDeviceModel@MapsIdました。これにより、CompositeKeyでのエンティティの使用が可能になりました。そのフィールドの@JoinColumnは、そのフィールドの名前付けを有効にしました。

DeviceModel model = new DeviceModel(); 
DeviceModelId modelId = new DeviceModelId(); 
modelId.setModelNumber(654321); 
// have to have a DeviceType to create a DeviceModel 
model.setDeviceType(type); 
model.setId(modelId); 

これは、あなたと一致するように見える次のスキーマを作成します。

create table devices (device_nbr bigint not null, device_id varchar(20), unit_addr varchar(32), dev_type integer, model_nbr integer, primary key (device_nbr)) 
create table devmodels (dev_type integer not null, model_nbr integer not null, model_desc varchar(20), primary key (dev_type, model_nbr)) 
create table devtypes (dev_type integer not null, dev_desc varchar(16), primary key (dev_type)) 
alter table devices add constraint FK8q0a886v04gg0qv261x1b2qrf foreign key (dev_type, model_nbr) references devmodels 
alter table devices add constraint FKb72a7hq5phwjtbhaglobdkgji foreign key (dev_type) references devtypes 
alter table devmodels add constraint FK4xlwyd2gwpbs4g4hdckyb11oj foreign key (dev_type) references devtypes 
+0

これは非常に有望です。私は明日それを試してみましょう! –

+0

チャームのように働いた。インターネットはとてもスマートです!ありがとうございました。 –

関連する問題