【问题标题】:How to combine manual insert and JPA Id generation?如何结合手动插入和 JPA Id 生成?
【发布时间】:2014-12-24 07:35:53
【问题描述】:

我正在使用 arquillian 运行容器内测试。我通过在部署中添加import.sql 来预填充数据库。在测试期间,我想创建更多实体。

不幸的是,这失败了PersistenceException

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException:唯一索引或 主键违规:“PRIMARY_KEY_BE ON PUBLIC.KVS_MIPO_DOWNLOAD(ID)"

如果我不预先填充数据库,或者不保留新实体,一切都会顺利进行。

id是唯一唯一的字段,所以我强烈怀疑它一定是使用序列的id生成。

@Entity
@Table(name = "KVS_MIPO_DOWNLOAD")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
public abstract class DownloadResource implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Integer id;

该实体是另一个具体实体的超类,不添加任何唯一属性。

可以做些什么来适应这两种可能性 - 手动插入和使用生成的 id?

谢谢

我在 JBoss 7.1.1 中通过 Hibernate 4.0.1 使用 JPA 2。数据库是 Sybase ASE 15。

编辑:到目前为止我发现的一种解决方法是将手动添加的实体的 ID 设置得足够高以避免冲突。但这对于生产来说还不够好——太多的员工对数据库有写访问权,并且可能会想手动添加东西。我希望应用程序足够健壮,不会在这种情况下死亡和爆炸。

【问题讨论】:

    标签: hibernate jpa jpa-2.0 jboss-arquillian


    【解决方案1】:

    为您的手动 ID 使用负值。 Hibernate 不应该产生负数。

    (可选)使用您自己的 id 生成器来跳过特定范围(或跳过可被 7 整除的数字;一些这样的方案)。

    示例 ID 生成器:

    import org.hibernate.HibernateException;
    import org.hibernate.engine.SessionImplementor;
    import org.hibernate.id.IdentifierGenerator;
    
    public class MyGenerator implements IdentifierGenerator {
    
        public Serializable generate(SessionImplementor session, Object object)
                throws HibernateException {
            return 1; // TODO: Your scheme to create an Integer;
        }
    }
    

    按如下方式使用此注解:

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "myid")
    @GenericGenerator(name = "myid", strategy = "com.x.y.z.MyDGenerator")
    public int getId() {
        return _id;
    }
    

    【讨论】:

    • 酷,我不知道可以使用负数。使用自定义生成器听起来也很合理,我要么生成负整数,要么从 Integer.MAX_VALUE 倒数。谢谢你,卡布拉姆
    【解决方案2】:

    您也可以使用 UUID 作为 id 或序列。手动添加的数据也可以引用序列。

    【讨论】:

    • +1。我现在正在使用香草休眠生成的序列。它只是从 1 开始并以 1 为增量,所以我想我将实现一个自定义生成器,如 kabram 提议的。 UUID 听起来也不错,我会研究一下。谢谢索伦西托
    • 我指的是数据库序列。这将 id 生成与应用程序分离。
    【解决方案3】:

    如果您使用 Fastnate,您可以创建具有正确 ID 的 import.sql,足以满足您的 JPA 模型和数据库的需要。

    例如,您可以通过这种方式创建实体:

    EntitySqlGenerator generator = new EntitySqlGenerator(new FileWriter("import.sql"));
    List<DownloadResource> resources = createDownloadResources();
    generator.write(resources);
    

    还有一些创建import.sql 的选项,但一开始就足够了。

    Fastnate 目前没有对 Sybase 的特殊支持,但对于大多数情况,默认方言 (H2) 也可以。

    【讨论】:

    • 听起来很有趣。然而,简单地删除一个工具名称只是一个好的开始;)您能否在您的答案中添加什么和如何的相关细节,一些最小可行的东西?
    • 我希望给定的例子就足够了。这个主题非常复杂,无法在一个答案中描述所有选项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 2018-07-23
    • 2017-10-10
    相关资源
    最近更新 更多