【问题标题】:Jpa composite key nullable columnsJpa 复合键可为空的列
【发布时间】:2010-10-15 00:25:38
【问题描述】:

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

  • 没有主键
  • 在 4 列上有唯一索引,其中 3 列可以为空

我试图破解它并将索引定义为复合 ID,但由于某些列可以为空,因此无法正常工作。 JPA/Hibernate 可以做到这一点吗?

谢谢

【问题讨论】:

    标签: java hibernate jpa composite-id


    【解决方案1】:

    似乎不可为空的列应该是您的主键。复合键的任何部分都不应该可以为空。

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

    此外,这看起来像是 Hibernate mapping a composite key with null values 的副本,当我在 Google 上搜索“空复合键”时,它出现在 #3。

    【讨论】:

    • 请注意,我不能将不可为空的列作为PK,因为列本身不是唯一的,只有列的组合。我知道这是糟糕的设计,但我无法控制 DB 模型。
    • 由于列的组合始终是唯一的(是否有空值)并且列集永远不会为空(因为不可为空的列)我认为可以这样做.
    • 数据库不应该允许这样做,但有些允许。不幸的是,您无法控制数据库模式。你能和控制模式的人交谈吗?抱歉,但我不知道有一种解决方法/黑客可以使这项工作与 hibernate 一起使用。
    • 感谢大家的帮助,但很遗憾我无法控制架构,但我会尝试看看所有者是否可以添加真正的 PK。
    • 我也有同样的问题。我有一个带有 4 个属性的 @Embedded(这是一个视图,我无法控制它)。其中一些可以为null,但它们的组成不能相同(ford,red,4,4),例如(ford,red,4,null)。我该怎么办?
    【解决方案2】:

    解决方法是...您应该实现自己的 UserType 实现并处理 null 值以为此返回一个代表对象。

    看看我的例子。该字段是一个可以为空的数字,所以我的实现是:

    看起来像在 HBM 文件中

       <key-property name="fieldName" type="mypackage.forUserTypes.DefaultLongType">
        <column name="FIELD_NAME" precision="10" scale="0" />
       </key-property>
    

    ...在 Java 中

    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;
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2010-09-19
      • 2016-03-08
      • 2013-03-19
      • 1970-01-01
      • 2014-09-12
      • 1970-01-01
      • 2011-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多