How to combine manual insert and JPA Id generation?

佐手、 提交于 2020-01-04 03:11:08

问题


I am running in-container tests with arquillian. I am prepopulating the database by adding an import.sql to the deployment. During the test I would like to create some more entities.

Unfortunately, this fails with a PersistenceException:

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Unique index or primary key violation: "PRIMARY_KEY_BE ON PUBLIC.KVS_MIPO_DOWNLOAD(ID)"

If I do not prepopulate the DB, or do not persist new entities, everything runs smoothly.

The id is the only unique field, so I strongly suspect that it must be the id generation using a sequence.

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

This entity is the superclass of another concrete entity, which does not add any unique attributes.

What can be done to be able to accomodate both possibilitiees - inserting manually and using a generated id?

Thank you

I am working with JPA 2 over Hibernate 4.0.1 in JBoss 7.1.1. The database is Sybase ASE 15.

EDIT: one workaround I have found so far is to set the Ids of the manually added entities high enough to avoid collisions. But this is not good enough for production - too many employees have write access to the db and may be tempted to add stuff manually. I would prefer the application to be robust enough not to die and explode in this case.


回答1:


Use negative values for your manual ids. Hibernate shouldn't generate negative ones.

Optionally, use your own id generator that skips a particular range (or skips say numbers divisible by 7; some such scheme).

Sample ID generator:

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

To use this annotate as follows:

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



回答2:


You could also use UUIDs as id or, alternatively, a sequence. Manually added data could refer to the sequence as well.




回答3:


If you use Fastnate you can create the import.sql with the correct IDs, sufficient for your JPA model and your database.

For example you could create your entities this way:

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

There are some more options to create the import.sql, but for a start that should be enough.

Fastnate has currently no special support for Sybase, but for most things the default dialect (H2) will work as well.



来源:https://stackoverflow.com/questions/14401475/how-to-combine-manual-insert-and-jpa-id-generation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!