问题
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