前段时间做的一个项目里面,由于关联关系用到了下面的一种一对多的关联关系.
对象继承:
根对象Information
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "informationtype", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue(value = "INFORMATION")
public class Information implements Serializable{
protected Category category;
......
public void setItem(Item item) {
this.item = item;
}
public void setCategory(Category category) {
this.category = category;
}
}
子对象AttachInformation
@Entity
@DiscriminatorValue("ATTACHINFORMATION")
public class AttachInformation extends Information{
private long size;
......
}
子对象BasicInformation
@Entity
@DiscriminatorValue("BASICINFORMATION")
public class BasicInformation extends Information implements Serializable{
private String description;
}
这样,子对象分别对根对象的值作了扩展,并采用的是继承关系一个表的结构.这样,在表information表中,分别对AttachInformation增加一个size(类型为big int),description(类型为varchar)的字段.现在有一个类,它分别对AttachInformation和BasicInformation有一个一对多的关联.关联关系如下
@Entity
public class Category implements Serializable{
private List<BasicInformation> basicInformationList;
private List<AttachInformation> attachInformationList;
......
@OneToMany(mappedBy = "category",cascade = CascadeType.REMOVE)
public List<BasicInformation> getBasicInformationList() {
return basicInformationList;
}
@OneToMany(mappedBy = "category",cascade = CascadeType.REMOVE)
public List<AttachInformation> getAttachInformationList() {
return attachInformationList;
}
}
可以看出,对象Category,分别对应多个BasicInformation和多个AttachInformation.采用一对多双向的关联,二者对Category的引用都采用getCategory()的方式,并且其引用的外键都是category_id.
这种关联方式在大多数应用下都没有问题,但是在当从category引用其关联的attachInformation或者basicInformation时,问题出现了.特别在当删除category时,由于关联删除,将查询出其attachInformationList和basicInformationList并且一个一个地删除(这种方式是由于由多一方负责进行关联).
在删除过程中出现了一个异常信息,描述为:can not turn a null value into primary type.大概意思就是说无法将一个空信息转化成基本类型.查看了一个输出的sql语句,发现当删除category时,出现一个查询关联对象的语句,而语句竟然是from Information为主体的,再用spy追踪了一下,发现是hibernate用这个hql语句将information查询出来,再分别将这些对象转化为具体的子类型,结果当遇到size为null时(这时候的类型为basicInformation),错误就发生了.
查看详细的sql语句,发现sql中并没有将informationtype='attachInformation'这个鉴别器加上,导致查询出的对象并非是完全正确类型的对象.在google中找了半天,并没有发现相应的信息,最后在hibernate手册中找到一个关于在继承中使用 强制鉴别的一个annotation(ForceDiscriminator).将这个加到根类的type上,重装运行程序.现在删除成功了.出现的sql语句已经将鉴别器带上了.
关于forcediscriminator这个东西,讲得很少.在关键时候还是帮了大忙.:)