【问题标题】:Do you have a common base class for Hibernate entities?你有 Hibernate 实体的通用基类吗?
【发布时间】:2010-09-14 11:25:22
【问题描述】:

您是否有 Hibernate 实体的通用基类,即具有 id、版本和其他通用属性的 MappedSuperclass?有什么缺点吗?

例子:

@MappedSuperclass()
public class BaseEntity {

    private Long id;
    private Long version;
    ...

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {return id;}

    public void setId(Long id) {this.id = id;}

    @Version
    public Long getVersion() {return version;}
    ...

    // Common properties
    @Temporal(TemporalType.TIMESTAMP)
    public Date creationDate() {return creationDate;}
    ...
}

@Entity
public class Customer extends BaseEntity {
    private String customerName;
    ...
}

【问题讨论】:

    标签: java hibernate entities base-class


    【解决方案1】:

    这对我也很有效。

    请注意,您还可以根据需要在此实体中添加一些事件侦听器/拦截器,例如 Hibernate Envers 或任何自定义的,以便您可以: - 跟踪所有修改 - 知道哪个用户进行了最后修改 - 自动更新最后一次修改 - 自动设置第一个插入日期 还有诸如此类的东西……

    【讨论】:

      【解决方案2】:

      【讨论】:

        【解决方案3】:

        我使用的主要是实现hashCode()和equals()。我还添加了一个漂亮地打印实体的方法。作为对上述 DR 的响应,其中大部分都可以被覆盖,但在我的实现中,您会遇到 Long 类型的 ID。

        public abstract class BaseEntity implements Serializable {
        
            public abstract Long getId();
            public abstract void setId(Long id);
        
            /**
             * @see java.lang.Object#hashCode()
             */
            @Override
            public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
                return result;
            }
        
            /**
             * @see java.lang.Object#equals(Object)
             */
            @Override
            public boolean equals(Object obj) {
                if (this == obj)
                    return true;
                if (obj == null)
                    return false;
                if (getClass() != obj.getClass())
                    return false;
                BaseEntity other = (BaseEntity) obj;
                if (getId() == null) {
                    if (other.getId() != null)
                        return false;
                } else if (!getId().equals(other.getId()))
                    return false;
                return true;
            }
        
            /**
             * @see java.lang.Object#toString()
             */
            @Override
            public String toString() {
                return new StringBuilder(getClass().getSimpleName()).append(":").append(getId()).toString();
            }
        
            /**
             * Prints complete information by calling all public getters on the entity.
             */
            public String print() {
        
                final String EQUALS = "=";
                final String DELIMITER = ", ";
                final String ENTITY_FORMAT = "(id={0})";
        
                StringBuffer sb = new StringBuffer("{");
        
                PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(this);
                PropertyDescriptor property = null;
                int i = 0;
                while ( i < properties.length) {
        
                    property = properties[i];
                    sb.append(property.getName());
                    sb.append(EQUALS);
        
                    try {
                        Object value = PropertyUtils.getProperty(this, property.getName());
                        if (value instanceof BaseEntity) {
                            BaseEntity entityValue = (BaseEntity) value;
                            String objectValueString = MessageFormat.format(ENTITY_FORMAT, entityValue.getId());
                            sb.append(objectValueString);
                        } else {
                            sb.append(value);
                        }
                    } catch (IllegalAccessException e) {
                        // do nothing
                    } catch (InvocationTargetException e) {
                        // do nothing
                    } catch (NoSuchMethodException e) {
                        // do nothing
                    }
        
                    i++;
                    if (i < properties.length) {
                        sb.append(DELIMITER);
                    }
                }
        
                sb.append("}");
        
                return sb.toString();
            }
        }
        

        【讨论】:

        • 对不起,您为什么要使用 while 循环来处理似乎更适合 for 循环的内容?
        • 是的,我本可以这样做: for (i = 0; i
        • 这个问题已经有一段时间了,但是,上面的 equals() 方法有一个错误,它可能会产生代理问题:而不是 getClass() != obj.getClass() 使用isAssignableFrom() 或 !(obj instanceof BaseEntity)
        • 我们一直在我们的实体上使用 lombok @EqualsAndHashCode 注释。这比我们自己编写更不容易出错。
        【解决方案4】:

        我会毫不犹豫地使用通用基类,毕竟这就是 O/R 映射的重点。

        我也使用公共基类,但前提是实体至少共享一些公共属性。如果 ID 是唯一的公共属性,我不会使用它。到目前为止,我没有遇到任何问题。

        【讨论】:

          【解决方案5】:

          这对我们来说很好。除了 ID 和创建日期,我们还有一个修改日期。我们还有一个实现 Taggable 接口的中间 TaggedBaseEntity,因为我们的一些 Web 应用程序的实体具有标签,例如 Stack Overflow 上的问题。

          【讨论】:

            猜你喜欢
            • 2018-10-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-06-19
            • 2022-01-22
            • 2013-12-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多