4

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.

kostja
  • 60,521
  • 48
  • 179
  • 224

3 Answers3

3

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;
}
Καrτhικ
  • 3,833
  • 2
  • 29
  • 42
  • Cool, I didn't know one could use negative numbers. Using a custom generator sounds reasonable too, I would either generate negative integers or count back from Integer.MAX_VALUE. Thank you, kabram – kostja Jan 18 '13 at 18:50
1

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

sorencito
  • 2,517
  • 20
  • 21
  • +1. I am using a vanilla hibernate-generated sequence now. It simply starts at 1 and increments by 1, so I guess I will implement a custom generator like kabram proposed. UUID sounds good too though, I'll look into it. Thank you sorencito – kostja Jan 18 '13 at 18:53
  • I was referring to a database sequence. This decouples the id generation from the application. – sorencito Jan 19 '13 at 11:05
1

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.

Tobias Liefke
  • 8,637
  • 2
  • 41
  • 58
  • Sounds interesting. However simply dropping a tool name is only a good start ;) Could you add the relevant details of what and how to your answer, something minimally viable? – kostja Dec 18 '14 at 03:37
  • I hope the given example is enough. The topic is far to complex to describe all the options in a single answer. – Tobias Liefke Dec 23 '14 at 23:36