I would like to make use @IndexColumn to set seq number of some data the user enters. I am using Spring 2.5.6, JBoss 5.1 (JPA 1.0).
For my parent class
@Entity
@Table(name="material")
public class Material implements Serializable {
.
.
/**
* List of material attributes associated with the given material
*/
@OneToMany(mappedBy = "material", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@IndexColumn(name="seq_number", base=0, nullable = false)
private List<MaterialAttribute> materialAttributes;
public void addMaterialAttribute(List<MaterialAttribute> attribs)
{
if(CollectionUtils.isNotEmpty(attribs))
{
for(MaterialAttribute attrib : attribs)
{
attrib.setMaterial(this);
}
this.setMaterialAttributes(attribs);
}
}
}
For my child class
@Entity
@Table(name="material_attribute")
public class MaterialAttribute implements Serializable
{
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "material_id", referencedColumnName = "id", updatable=false, nullable = true, unique = false)
private Material material;
@Column(name = "seq_number", insertable=false, updatable=false, nullable = false)
private int seqNumber;
}
For the service class
public void save(MaterialCommand pCmd)
{
Material material = new Material(pCmd.getName());
//convert from command object to entity object
List<MaterialAttribute> attribs = new ArrayList<MaterialAttribute>();
if(CollectionUtils.isNotEmpty(pCmd.getAttribs()))
{
Iterator<MaterialAttributeCommand> iter = pCmd.getAttribs().iterator();
while(iter.hasNext())
{
MaterialAttributeCommand attribCmd = (MaterialAttributeCommand) iter.next();
MaterialAttribute attrib = new MaterialAttribute();
attrib.setDisplayName(attribCmd.getDisplayName());
attrib.setValidationType(attribCmd.getValidationType());
attribs.add(attrib);
}
}
material.addMaterialAttribute(attribs);
this.getMaterialDAO().saveMaterial(material);
}
I am getting entries into the database but the seq_number is always zero, for every item in the collection.
I have to assume it is in the way that I am saving the data but I just do not see it.
I have been able to solve the issue doing the following (removed the mappedBy):
@Entity
@Table(name="material")
public class Material implements Serializable {
/**
*
*/
private static final long serialVersionUID = 5083931681636496023L;
@Column(name="name", length=50, nullable=false)
private String mName;
/**
* List of material attributes associated with the given material
*/
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@IndexColumn(name="seq_number", base=0)
@JoinColumn(name="material_id",nullable=false)
private List<MaterialAttribute> materialAttributes;
@Entity
@Table(name="material_attribute")
public class MaterialAttribute implements Serializable
{
/**
*
*/
private static final long serialVersionUID = -196083650806575093L;
/**
* identifies the material that these attributes are associated with
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "material_id", insertable=false, updatable=false, nullable = true, unique = false)
private Material material;
@Column(name = "seq_number", insertable=false, updatable=false)
private int seqNumber;
Mapping a bidirectional indexed List with Hibernate is a bit tricky but is covered in the section 2.4.6.2.1. Bidirectional association with indexed collections of the documentation (bold is mine):
Actually, the second mapping is precisely how to map a bidirectional one to many with the one-to-many side as the owning side. While this is possible, you need to be aware that this kind of mapping will produce under optimized SQL as stated in the section about 2.2.5.3.1.1. Bidirectional [One-to-many] relations:
To sum up, if mapping the index column as a property of the target entity is not a concern, this would be my recommendation (i.e. the first mapping).
References