Java Jpa复合键可为空列

Java Jpa复合键可为空列,java,hibernate,jpa,composite-id,Java,Hibernate,Jpa,Composite Id,我正在使用Hibernate的JPA impl对一些表进行建模。我在映射以下表时遇到问题: 没有主键 在4列上具有唯一索引,其中3列可以为空 我试图破解它,并将索引定义为复合Id,但由于某些列可为空,因此无法正常工作。JPA/Hibernate是否可以实现这一点 谢谢看起来不可为空的列应该是您的主键。复合密钥的任何部分都不应为空 您需要获取可为null的属性,并将它们放置在主键/复合键之外 而且,当我在谷歌上搜索“空复合键”时,这看起来像是一个副本,它显示为#3。。。您应该实现自己的User

我正在使用Hibernate的JPA impl对一些表进行建模。我在映射以下表时遇到问题:

  • 没有主键
  • 在4列上具有唯一索引,其中3列可以为空
我试图破解它,并将索引定义为复合Id,但由于某些列可为空,因此无法正常工作。JPA/Hibernate是否可以实现这一点


谢谢

看起来不可为空的列应该是您的主键。复合密钥的任何部分都不应为空

您需要获取可为null的属性,并将它们放置在主键/复合键之外


而且,当我在谷歌上搜索“空复合键”时,这看起来像是一个副本,它显示为#3。。。您应该实现自己的UserType实现,并处理null值以返回此对象的代表性对象

看看我的例子。该字段是可为空的数字,因此我的实现是:

在HBM文件中看起来像:

   <key-property name="fieldName" type="mypackage.forUserTypes.DefaultLongType">
    <column name="FIELD_NAME" precision="10" scale="0" />
   </key-property>
public class DefaultLongType implements UserType {
private static final long serialVersionUID = 1L;

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#assemble(java.io.Serializable, java.lang.Object)
 */
public Object assemble(Serializable cached, Object owner)
        throws HibernateException {
    return null;
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#deepCopy(java.lang.Object)
 */
public Object deepCopy(Object value) throws HibernateException {
    return null;
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#disassemble(java.lang.Object)
 */
public Serializable disassemble(Object value) throws HibernateException {
    return null;
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#equals(java.lang.Object, java.lang.Object)
 */
public boolean equals(Object x, Object y) throws HibernateException {
    if (x == y) return true;
    if (x == null) return false;
    return x.equals(y);
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#hashCode(java.lang.Object)
 */
public int hashCode(Object x) throws HibernateException {
    return x == null ? 0 : x.hashCode();
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#isMutable()
 */
public boolean isMutable() {
    return false;
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
 */
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
        throws HibernateException, SQLException {
    final long value = rs.getLong(names[0]);
    if (rs.wasNull()) {
        return new Long(Long.MIN_VALUE);
    }
    return new Long(value);
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
 */
public void nullSafeSet(PreparedStatement st, Object value, int index)
        throws HibernateException, SQLException {
    Long l = (Long) value;
    if (l == null || l.longValue() == Long.MIN_VALUE) {
        st.setNull(index, Types.NUMERIC);
    }
    else {
        st.setLong(index, l.longValue());
    }
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#replace(java.lang.Object, java.lang.Object, java.lang.Object)
 */
public Object replace(Object original, Object target, Object owner)
        throws HibernateException {
    return original;
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#returnedClass()
 */
public Class returnedClass() {
    return Long.class;
}

/* (non-Javadoc)
 * @see org.hibernate.usertype.UserType#sqlTypes()
 */
public int[] sqlTypes() {
    final int[] args = { Types.NUMERIC };
    return args;
}
}

请注意,我不能将不可为null的列作为PK,因为该列本身不是唯一的,只是列的组合。我知道这是一个糟糕的设计,但我无法控制DB模型。由于列的组合总是唯一的(无论是否有空值),并且列集从不为空(因为不可为空的列),我认为这是可以做到的。数据库不应该允许这样做,但有些数据库允许这样做。不幸的是,您无法控制数据库模式。你能和控制模式的人交谈吗?很抱歉,我不知道有什么解决方法/黑客可以让hibernate起作用。感谢所有的帮助,但不幸的是我无法控制模式,但我会尝试看看所有者是否可以添加一个真正的PK。我也有同样的问题。我有一个嵌入了4个属性的@(这是一个视图,我无法控制它)。其中一些可以为null,但它们的组成不能相同(例如,福特,红色,4,4),(福特,红色,4,null)。我该怎么办?