2009-10-15 4 views
0

J'ai 2 tables, périphériques qui contient une liste de périphériques et dev_tags, qui contient une liste d'étiquettes d'actifs pour ces périphériques. Les tables se joignent à dev_serial_num, qui est la clé primaire d'aucune table. Les périphériques sont uniques sur leur champ ip_address et ils ont une clé primaire identifiée par dev_id. Les appareils "vieillissent" après 2 semaines. Par conséquent, le même morceau de matériel peut apparaître plus d'une fois dans les appareils.@OneToMany association se joignant sur le mauvais champ

Je mentionne cela pour expliquer pourquoi il existe une relation OneToMany entre les dev_tags et les périphériques où il semble que cela devrait être une relation OneToOne.

J'ai donc mes 2 entités

@Entity 
@Table(name = "dev_tags") 
public class DevTags implements Serializable { 

private Integer tagId; 
private String devTagId; 
private String devSerialNum; 
private List<Devices> devices; 

@Id 
@GeneratedValue 
@Column(name = "tag_id") 
public Integer getTagId() { 
    return tagId; 
} 

public void setTagId(Integer tagId) { 
    this.tagId = tagId; 
} 

@Column(name="dev_tag_id") 
public String getDevTagId() { 
    return devTagId; 
} 

public void setDevTagId(String devTagId) { 
    this.devTagId = devTagId; 
} 

@Column(name="dev_serial_num") 
public String getDevSerialNum() { 
    return devSerialNum; 
} 

public void setDevSerialNum(String devSerialNum) { 
    this.devSerialNum = devSerialNum; 
} 


@OneToMany(mappedBy="devSerialNum") 
public List<Devices> getDevices() { 
    return devices; 
} 

public void setDevices(List<Devices> devices) { 
    this.devices = devices; 
} 


} 

et celui-ci

public class Devices implements java.io.Serializable { 

private Integer devId; 
private Integer officeId; 
private String devSerialNum; 
private String devPlatform; 
private String devName; 
private OfficeView officeView; 
private DevTags devTag; 

public Devices() { 
} 

@Id 
@GeneratedValue(strategy = IDENTITY) 
@Column(name = "dev_id", unique = true, nullable = false) 
public Integer getDevId() { 
    return this.devId; 
} 

public void setDevId(Integer devId) { 
    this.devId = devId; 
} 

@Column(name = "office_id", nullable = false, insertable=false, updatable=false) 
public Integer getOfficeId() { 
    return this.officeId; 
} 

public void setOfficeId(Integer officeId) { 
    this.officeId = officeId; 
} 

@Column(name = "dev_serial_num", nullable = false, length = 64, insertable=false, updatable=false) 
@NotNull 
@Length(max = 64) 
public String getDevSerialNum() { 
    return this.devSerialNum; 
} 

public void setDevSerialNum(String devSerialNum) { 
    this.devSerialNum = devSerialNum; 
} 

@Column(name = "dev_platform", nullable = false, length = 64) 
@NotNull 
@Length(max = 64) 
public String getDevPlatform() { 
    return this.devPlatform; 
} 

public void setDevPlatform(String devPlatform) { 
    this.devPlatform = devPlatform; 
} 

@Column(name = "dev_name") 
public String getDevName() { 
    return devName; 
} 

public void setDevName(String devName) { 
    this.devName = devName; 
} 

@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "office_id") 
public OfficeView getOfficeView() { 
    return officeView; 
} 

public void setOfficeView(OfficeView officeView) { 
    this.officeView = officeView; 
} 

@ManyToOne() 
@JoinColumn(name="dev_serial_num") 
public DevTags getDevTag() { 
    return devTag; 
} 

public void setDevTag(DevTags devTag) { 
    this.devTag = devTag; 
} 

} 

Je foiré autour d'un lot avec @JoinColumn (name =) et l'attribut mappedBy de @OneToMany et je ne peux pas fais ce droit. J'ai finalement eu la chose à compiler, mais la requête essaye toujours de joindre devices.dev_serial_num à dev_tags.tag_id, le @Id pour cette entité. Voici la transcription de la console:

13:12:16,970 INFO [STDOUT] Hibernate: 
select 
    devices0_.office_id as office5_2_, 
    devices0_.dev_id as dev1_2_, 
    devices0_.dev_id as dev1_156_1_, 
    devices0_.dev_name as dev2_156_1_, 
    devices0_.dev_platform as dev3_156_1_, 
    devices0_.dev_serial_num as dev4_156_1_, 
    devices0_.office_id as office5_156_1_, 
    devtags1_.tag_id as tag1_157_0_, 
    devtags1_.comment as comment157_0_, 
    devtags1_.dev_serial_num as dev3_157_0_, 
    devtags1_.dev_tag_id as dev4_157_0_ 
from 
    ond.devices devices0_ 
left outer join 
    ond.dev_tags devtags1_ 
     on devices0_.dev_serial_num=devtags1_.tag_id 
where 
    devices0_.office_id=? 
13:12:16,970 INFO [IntegerType] could not read column value from result set: dev4_156_1_; Invalid value for getInt() - 'FDO1129Y2U4' 
13:12:16,970 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: S1009 
13:12:16,970 ERROR [JDBCExceptionReporter] Invalid value for getInt() - 'FDO1129Y2U4' 

Cette valeur pour getInt() « FD01129Y2U4 » est un numéro de série, certainement pas un Int! Qu'est-ce qui me manque/malentendu ici? Est-ce que je peux joindre 2 tables sur n'importe quels champs que je veux ou au moins un doit-il être une clé primaire?

Répondre

0

La réponse courte est "non, vous ne pouvez pas joindre 2 tables sur des champs"; L'association se référera toujours à la clé primaire d'un côté.

attribut « mappedBy » pour @OneToMany est utilisé pour bi-directional assocations et spécifie le nom de la propriété sur l'élément de collection qui mappe retour à l'entité propriétaire comme @ManyToOne. Dans votre cas,

@OneToMany(mappedBy="devSerialNum") 

la déclaration est invalide; il devrait être changé à

@OneToMany(mappedBy="devTag") 

à la place si vous voulez maintenir une relation bidirectionnelle. @JoinColumn peut être utilisé avec @ManyToOne pour spécifier le nom de la colonne (clé étrangère) pointant vers l'autre table. Dans votre cas,

@ManyToOne() 
@JoinColumn(name="dev_serial_num") 
public DevTags getDevTag() { 
déclaration

dit que vous avez une colonne appelée dev_serial_num dans votre table devices qui sera une clé étrangère pointant à dev_tags.tag_id qui est également faux. Je ne comprends pas très bien ce que vous entendez par «vieillissement des périphériques», mais il me semble que vous essayez de fusionner deux concepts distincts en une seule table, d'où proviennent tous ces problèmes. Considérez à la place de séparer votre table "devices" (et l'entité) en deux:

  1. "Core" périphérique (pour le manque de meilleur nom) devrait contenir des attributs vraiment uniques, comme le numéro de série. Votre entité DevTags sera liée de façon un-à-plusieurs à celle-ci.
  2. Le dispositif "version" contiendrait des attributs applicables à une "version" individuelle. Il y aura plusieurs «versions» pour chaque dispositif «de base»; "version" est ce qui sera mis à jour toutes les 2 semaines.
Questions connexes