@IndexColumn的使用导致seq_num为0 [英] Usage of @IndexColumn results in a seq_num of 0

查看:129
本文介绍了@IndexColumn的使用导致seq_num为0的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用@IndexColumn来设置用户输入的某些数据的seq数量。我使用Spring 2.5.6,JBoss 5.1(JPA 1.0)。

对于我的父类



<$ p $
@Table(name =material)
public class Material实现Serializable {


/ **
*与给定材料关联的材质属性列表
* /
@OneToMany(mappedBy =material,cascade = CascadeType.ALL,fetch = FetchType。 EAGER)
@IndexColumn(name =seq_number,base = 0,nullable = false)
private List< MaterialAttribute> materialAttributes;

公共无效addMaterialAttribute(列表与LT; MaterialAttribute> attribs)
{
如果(CollectionUtils.isNotEmpty(attribs))
{
为(MaterialAttribute ATTRIB: attribs)
{
attrib.setMaterial(this);
}

this.setMaterialAttributes(attribs);



$ b $ / code>

对于我的子类class




$ @ b $ b $ @ bable(name =material_attribute)
public class MaterialAttribute implements Serializable
{

@ManyToOne(取= FetchType.LAZY)
@JoinColumn(name = material_id,referencedColumnName = ID,可更新=假,可为空=真,独特= false)
私人素材;

@Column(name =seq_number,insertable = false,updatable = false,nullable = false)
private int seqNumber;
}

对于服务类别



公共无效保存(MaterialCommand pCmd)
{
材质材质=新材质(pCmd.getName());

  

//从命令对象转换为实体对象
List< MaterialAttribute> attribs = new ArrayList< MaterialAttribute>();

if(CollectionUtils.isNotEmpty(pCmd.getAttribs()))
{
Iterator< MaterialAttributeCommand> iter = pCmd.getAttribs()。iterator(); (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);
}

我得到数据库中的条目,但seq_number总是为零,项目。



我必须假定它是保存数据的方式,但我只是没有看到它。






我已经能够解决以下问题(移除mappedBy):

  @Entity 
@Table(name =material)
public class Material实现Serializable {

/ **
*
* /
private static final long serialVersionUID = 5083931681636496023L;

@Column(name =name,length = 50,nullable = false)
private String mName;
$ b $ / **
*与给定材料关联的材质属性列表
* /
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@IndexColumn(名称= seq_number,基部= 0)
@JoinColumn(名称= material_id,可为空=假)
私人列表与LT; MaterialAttribute> materialAttributes;


$ b @Entity
@Table(name =material_attribute)
public class MaterialAttribute implements Serializable
{

/ **
*
* /
private static final long serialVersionUID = -196083650806575093L;
$ b / **
*标识这些属性与
* /
关联的材质@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn (name =material_id,insertable = false,updatable = false,nullable = true,unique = false)
private材质材质;

@Column(name =seq_number,insertable = false,updatable = false)
private int seqNumber;


解决方案

映射 双向使用Hibernate索引列表有点棘手,但在 2.4.6.2.1。文档中的双向关联与索引集合(粗体是我的):


2.4.6.2.1。与索引集合的双向关联



一个双向关联,其中一个
end是一个索引集合(即。
表示为 @OrderColumn ,或者作为
a Map )需要考虑特殊的
如果
关联类中的某个属性显式映射了
索引值,则允许使用 mappedBy

  @Entity 
public class Parent {
@OneToMany(mappedBy =parent)
@OrderColumn(name =order)
private List< Child>儿童;
...
}

@Entity
public class Child {
...
//索引列映射为相关实体中的属性
@Column(name =order)
private int order;

@ManyToOne
@JoinColumn(name =parent_id,nullable = false)
私有父母;
...
}

但是,如果没有这样的属性
子类,我们不能将
关联看作真正的
双向
(在$ b的一端有可用信息
$ b关联不可用于
另一端:索引)。在这个
的情况下,我们不能将这个集合映射为
mappedBy 。相反,我们可以使用
映射:

  @Entity 
public class Parent {
@OneToMany
@OrderColumn(name =order)
@JoinColumn(name =parent_id,nullable = false)
private List< Child>儿童;
...
}

@Entity
public class Child {
...
@ManyToOne
@JoinColumn( name =parent_id,insertable = false,updatable = false,nullable = false)
私有父亲;
...
}

请注意,在此映射中,
关联的
集合值结尾负责更新外键


实际上,第二种映射正是如何将一对多边作为拥有者来映射双向一对多。虽然这是可能的,但您需要知道,这种映射将在优化的SQL下生成,如 2.2.5.3.1.1。双向 [一对多]关系:


为了映射一个双向多对象
,一对多作为
拥有方,您必须除去
mappedBy 元素并将许多元素设置为
一个 @JoinColumn 作为可插入
可更新这个解决方案是
没有优化的,并且会产生额外的
额外的UPDATE语句。

总而言之,如果将索引列映射为目标实体的属性不是问题,那么这将是我的建议(即第一个映射)。 参考文献


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

2.4.6.2.1. Bidirectional association with indexed collections

A bidirectional association where one end is an indexed collection (ie. represented as a @OrderColumn, or as a Map) requires special consideration. If a property on the associated class explicitly maps the indexed value, the use of mappedBy is permitted:

@Entity
public class Parent {
    @OneToMany(mappedBy="parent")
    @OrderColumn(name="order")
    private List<Child> children;
    ...
}

@Entity
public class Child {
    ...
    //the index column is mapped as a property in the associated entity
    @Column(name="order")
    private int order;

    @ManyToOne
    @JoinColumn(name="parent_id", nullable=false)
    private Parent parent;
    ...
}

But, if there is no such property on the child class, we can't think of the association as truly bidirectional (there is information available at one end of the association that is not available at the other end: the index). In this case, we can't map the collection as mappedBy. Instead, we could use the following mapping:

@Entity
public class Parent {
    @OneToMany
    @OrderColumn(name="order")
    @JoinColumn(name="parent_id", nullable=false)
    private List<Child> children;
    ...
}

@Entity    
public class Child {    
    ...
    @ManyToOne
    @JoinColumn(name="parent_id", insertable=false, updatable=false, nullable=false)
    private Parent parent;
    ...
}

Note that in this mapping, the collection-valued end of the association is responsible for updating the foreign key.

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 map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy element and set the many to one @JoinColumn as insertable and updatable to false. This solution is not optimized and will produce some additional UPDATE statements.

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

这篇关于@IndexColumn的使用导致seq_num为0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆