JBoss EAP 4.3.0_CP01
Seam 2.0.1.GA
Hibernate 3.2.4.sp1.cp03
Windows 2003
I have a Seam app which is using JPA/Hibernate as its persistence provider.
I have a form with multiple input fields (h:inputText, h:selectOneMenu).
Some of these fields are persisting successfully via SMPC EntityManager by using manual flush (i.e. flush() is called on @End method).
Problem is that one drop-down selection drives another which in turn drives another.
I am having an issue with the following.
This is a seam-gen'd app and the entities were reverse engineered using seam-gen or some other form of hbm2java tool.
I noticed that one of the fields in tbHardware table was missing a getter and setter. So I added it myself:
Code:
@Column(name = "HardwareModelID", nullable = false)
public int getHardwareModelId() {
return this.hardwareModelId;
}
public void setHardwareModelId(int hardwareModelId) {
this.hardwareModelId = hardwareModelId;
}
Now when I deploy the app, I get
Code:
--- MBEANS THAT ARE THE ROOT CAUSE OF THE PROBLEM ---
ObjectName: persistence.units:ear=SHIMS.ear,jar=SHIMS.jar,unitName=SHIMS
State: FAILED
Reason: javax.persistence.PersistenceException: org.hibernate.MappingException: Repeated column in mapping for entity: com.cox.shims.entity.TbHardware column: HardwareModelID (should be mapped with insert="false" update="false")
I Depend On:
jboss.jca:service=DataSourceBinding,name=SHIMSDatasource
So apparently the problem is that I can't have "HardwareModelID" as the name attribute in more than one @Column annotation.
When I specify the table attribute in both @Column annotations, it can't find the corresponding tables.
I'm pretty sure than @SecondaryTable does not apply in this case (the primary and secondary tables must have the same primary key, which is not the case here).
So one solution is to simply change the column name in one of the tables. But must I do this to solve this problem? Or is a database schema refactoring in order (i.e. save the data in the other table - which I can't b/c it's a lookup table)?
entity:
Code:
@Entity
@Table(name = "tbHardware")
@Name("tbHardware")
public class TbHardware implements java.io.Serializable {
@Logger
Log log; //externalizable (according to Pete Muir) which implements serializable
private int hardwareId;
private TbLocation tbLocation;
private TrOwnerType trOwnerType;
private TrHardwareStatus trHardwareStatus;
private TbHardwareModel tbHardwareModel;
private int hardwareModelId;
private String coxBarcode;
private String serialNo;
private String description;
private Date firstEnteredDate;
private String enteredByUser;
private Date lastAuditedDate;
private BigDecimal hardwarePrice;
private String lastUsedByNetworkId;
private Set<TbSoftwareInstance> tbSoftwareInstances = new HashSet<TbSoftwareInstance>(
0);
private Set<TbHardwareNote> tbHardwareNotes = new HashSet<TbHardwareNote>(0);
private boolean isSelected;
public TbHardware() {
}
public TbHardware(int hardwareId, TbLocation tbLocation,
TrOwnerType trOwnerType, TrHardwareStatus trHardwareStatus,
TbHardwareModel tbHardwareModel, String coxBarcode, String serialNo, int hardwareModelId) {
this.hardwareId = hardwareId;
this.tbLocation = tbLocation;
this.trOwnerType = trOwnerType;
this.trHardwareStatus = trHardwareStatus;
this.tbHardwareModel = tbHardwareModel;
this.coxBarcode = coxBarcode;
this.serialNo = serialNo;
this.hardwareModelId = hardwareModelId;
}
public TbHardware(int hardwareId, TbLocation tbLocation,
TrOwnerType trOwnerType, TrHardwareStatus trHardwareStatus,
TbHardwareModel tbHardwareModel, int hardwareModelId, String coxBarcode,
String serialNo, String description, Date firstEnteredDate,
String enteredByUser, Date lastAuditedDate,
BigDecimal hardwarePrice, String lastUsedByNetworkId,
Set<TbSoftwareInstance> tbSoftwareInstances,
Set<TbHardwareNote> tbHardwareNotes) {
this.hardwareId = hardwareId;
this.tbLocation = tbLocation;
this.trOwnerType = trOwnerType;
this.trHardwareStatus = trHardwareStatus;
this.tbHardwareModel = tbHardwareModel;
this.hardwareModelId = hardwareModelId;
this.coxBarcode = coxBarcode;
this.serialNo = serialNo;
this.description = description;
this.firstEnteredDate = firstEnteredDate;
this.enteredByUser = enteredByUser;
this.lastAuditedDate = lastAuditedDate;
this.hardwarePrice = hardwarePrice;
this.lastUsedByNetworkId = lastUsedByNetworkId;
this.tbSoftwareInstances = tbSoftwareInstances;
this.tbHardwareNotes = tbHardwareNotes;
}
@Id
@Column(name = "HardwareID", unique = true, nullable = false)
public int getHardwareId() {
return this.hardwareId;
}
public void setHardwareId(int hardwareId) {
this.hardwareId = hardwareId;
}
@Column(name = "HardwareModelID", nullable = false)
public int getHardwareModelId() {
return this.hardwareModelId;
}
public void setHardwareModelId(int hardwareModelId) {
this.hardwareModelId = hardwareModelId;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CurrentLocationNo", nullable = false)
public TbLocation getTbLocation() {
return this.tbLocation;
}
public void setTbLocation(TbLocation tbLocation) {
this.tbLocation = tbLocation;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "OwnerTypeCode", nullable = false)
public TrOwnerType getTrOwnerType() {
return this.trOwnerType;
}
public void setTrOwnerType(TrOwnerType trOwnerType) {
this.trOwnerType = trOwnerType;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CurrentStatus", nullable = false)
public TrHardwareStatus getTrHardwareStatus() {
return this.trHardwareStatus;
}
public void setTrHardwareStatus(TrHardwareStatus trHardwareStatus) {
this.trHardwareStatus = trHardwareStatus;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "HardwareModelID", nullable = false)
public TbHardwareModel getTbHardwareModel() {
return this.tbHardwareModel;
}
public void setTbHardwareModel(TbHardwareModel tbHardwareModel) {
this.tbHardwareModel = tbHardwareModel;
}
@Column(name = "CoxBarcode", nullable = false, length = 200)
//AS 05-08-08 - moving some validations for barcode here from SFSB processValueChange()...
@Pattern(regex="^\\d{5}$", message="Please enter a 5-digit numeric barcode (ex: 01234) for row #{hardwareAndHardwareNoteList.getRowIndex()+1}")
public String getCoxBarcode() {
return this.coxBarcode;
}
public void setCoxBarcode(String coxBarcode) {
this.coxBarcode = coxBarcode;
}
@Column(name = "SerialNo", nullable = false, length = 50)
public String getSerialNo() {
return this.serialNo;
}
public void setSerialNo(String serialNo) {
this.serialNo = serialNo;
}
@Column(name = "Description", length = 200)
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
@Column(name = "FirstEnteredDate", length = 23)
public Date getFirstEnteredDate() {
return this.firstEnteredDate;
}
public void setFirstEnteredDate(Date firstEnteredDate) {
this.firstEnteredDate = firstEnteredDate;
}
@Column(name = "EnteredByUser", length = 50)
public String getEnteredByUser() {
return this.enteredByUser;
}
public void setEnteredByUser(String enteredByUser) {
this.enteredByUser = enteredByUser;
}
@Column(name = "LastAuditedDate", length = 23)
public Date getLastAuditedDate() {
return this.lastAuditedDate;
}
public void setLastAuditedDate(Date lastAuditedDate) {
this.lastAuditedDate = lastAuditedDate;
}
@Column(name = "HardwarePrice", scale = 4)
public BigDecimal getHardwarePrice() {
return this.hardwarePrice;
}
public void setHardwarePrice(BigDecimal hardwarePrice) {
this.hardwarePrice = hardwarePrice;
}
@Column(name = "LastUsedByNetworkID")
public String getLastUsedByNetworkId() {
return this.lastUsedByNetworkId;
}
public void setLastUsedByNetworkId(String lastUsedByNetworkId) {
this.lastUsedByNetworkId = lastUsedByNetworkId;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "tbHardware")
public Set<TbSoftwareInstance> getTbSoftwareInstances() {
return this.tbSoftwareInstances;
}
public void setTbSoftwareInstances(
Set<TbSoftwareInstance> tbSoftwareInstances) {
this.tbSoftwareInstances = tbSoftwareInstances;
}
//@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "tbHardware")
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "tbHardware")
public Set<TbHardwareNote> getTbHardwareNotes() {
return this.tbHardwareNotes;
}
public void setTbHardwareNotes(Set<TbHardwareNote> tbHardwareNotes) {
this.tbHardwareNotes = tbHardwareNotes;
}
@Transient
public boolean getIsSelected() {
return isSelected;
}
public void setIsSelected(boolean selected) {
this.isSelected = selected;
}
}