I am new in hibernate, and I am experiencing the following problem. "Unique index or primary key violation". The problem appears due to the wrong mapping, but I spend hours to figure out why it is happening.
I have one super class called DataStructure
#Entity
#Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class DataStructure {
private int DS_ID;
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
public int getDataStructureID() {
return DS_ID;
}
Then the class Association which associate two elements. Some parts of the class are omitted here, just to simplify it.
#Entity
public class AssociationTemporal extends DataStructure {
private DataStructure elementA;
private DataStructure elementB;
#OneToOne
public DataStructure getElementA() {
return elementA;
}
public void setElementA(DataStructure elementA) {
this.elementA = elementA;
}
#OneToOne
public DataStructure getElementB() {
return elementB;
}
public void setElementB(DataStructure elementB) {
this.elementB = elementB;
}
}
This class serves as middle class between two classes of DataStructure type. Like this.
TP-Association-TP
TP class:
#Entity
public class TP extends DataStructure {
List<AssociationTemporal> listOfAssociatedTPs = new ArrayList<AssociationTemporal>();
#OneToMany
public List<AssociationTemporal> getListOfAssociatedTPs() {
return listOfAssociatedTPs;
}
public void setListOfAssociatedTPs(List<AssociationTemporal> listOfAssociatedTPs) {
this.listOfAssociatedTPs = listOfAssociatedTPs;
}
}
Or activites class
#Entity
public class Activities extends DataStructure {
String name;
List<AssociationTemporal> listOfAsso = new ArrayList<AssociationTemporal>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany
public List<AssociationTemporal> getListOfAsso() {
return listOfAsso;
}
public void setListOfAsso(List<AssociationTemporal> listOfAsso) {
this.listOfAsso = listOfAsso;
}
}
In the main I have added the following:
AssociationTemporal at = new AssociationTemporal();
TP tp1 = new TP();
TP tp2 = new TP();
at.setElementA(tp1);
at.setElementB(tp2);
session.save(tp1);
session.save(tp2);
session.save(at);
tp1.getListOfAssociatedTPs().add(at);
tp2.getListOfAssociatedTPs().add(at);
session.getTransaction().commit();
The problem occurs as soon as I try to add the same object of
tp1.getListOfAssociatedTPs().add(at);
tp2.getListOfAssociatedTPs().add(at);
Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "UK_12JEPI3MP039NKMGO47YW1HBI_INDEX_A ON PUBLIC.TP_ASSOCIATIONTEMPORAL(LISTOFASSOCIATEDTPS_DATASTRUCTUREID) VALUES (32770, 1)"; SQL statement:
insert into PUBLIC.TP_AssociationTemporal (TP_dataStructureID, listOfAssociatedTPs_dataStructureID) values (?, ?) [23505-183]
By the same mean the association can be made with Activities, etc...
Just use GenerationType.SEQUENCE and it will fix the problem.
Related
I'm trying to implement a tree structure in JPA, that I want mapped to an H2 database using EclipseLink. The nodes of the tree are possibly subclasses of the base node class. What is happening is that EL is creating a brain-dead link table for the children as follows:
[EL Fine]: sql: 2015-04-10 13:26:08.266--ServerSession(667346055)--Connection(873610597)--CREATE TABLE ORGANIZATIONNODE_ORGANIZATIONNODE (OrganizationNode_IDSTRING VARCHAR NOT NULL, children_IDSTRING VARCHAR NOT NULL, Device_IDSTRING VARCHAR NOT NULL, monitors_IDSTRING VARCHAR NOT NULL, PRIMARY KEY (OrganizationNode_IDSTRING, children_IDSTRING, Device_IDSTRING, monitors_IDSTRING))
OrganizationNode is the proper superclass of Device. Both of these are #Entity, OrganizationNode extends AbstractEntity, which is a #MappedSuperclass where the #Id is defined (it is a string). Even stranger, while there is a Monitor class that is not in the tree structure, the only place "monitors" plural occurs is as a field of Device... what??
Now, it's fine to use a table like that to implement a tree structure, but I don't expect a compound primary key with separate instances of the Id field for each subclass! That's got to break - because some children are not Device, and therefore do not have a "Device_IDSTRING", and sure enough:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException|Internal Exception: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "DEVICE_IDSTRING"; SQL statement:|INSERT INTO ORGANIZATIONNODE_ORGANIZATIONNODE (children_IDSTRING, OrganizationNode_IDSTRING) VALUES (?, ?) [23502-186]|Error Code: 23502|Call: INSERT INTO ORGANIZATIONNODE_ORGANIZATIONNODE (children_IDSTRING, OrganizationNode_IDSTRING) VALUES (?, ?)|?bind => [2 parameters bound]|Query: DataModifyQuery(name="children" sql="INSERT INTO ORGANIZATIONNODE_ORGANIZATIONNODE (children_IDSTRING, OrganizationNode_IDSTRING) VALUES (?, ?)")
This seems like truly bizarre behavior. I've tried every combination of mapping annotations I could possibly think of to fix it. Any ideas?
Classes follow.
AbstractEntity.java:
#MappedSuperclass
public abstract class AbstractEntity {
// #Converter(name="uuidConverter",converterClass=UUIDConverter.class)
transient UUID id = null;
#Id String idString;
static long sequence = 1;
static long GREGORIAN_EPOCH_OFFSET = 12219292800000L;
public AbstractEntity() {
ThreadContext tctx = ThreadContext.getThreadContext();
long msb = tctx.getNodeID();
long lsb = (System.currentTimeMillis()+GREGORIAN_EPOCH_OFFSET) * 1000 + ((sequence++) % 1000);
lsb = (lsb & 0xCFFFFFFFFFFFFFFFL) | (0x8000000000000000L);
msb = (msb & 0xFFFFFFFFFFFF0FFFL) | (0x0000000000001000L);
id = new UUID(msb,lsb);
idString = id.toString();
}
#Id
public UUID getUUID() {
return id;
}
public String getIdString() {
return idString;
}
public void setIdString(String idString) {
this.idString = idString;
this.id = UUID.fromString(idString);
}
void setUUID(UUID id) {
this.id = id;
this.idString = id.toString();
}
#Override
public String toString() {
return "["+this.getClass().getCanonicalName()+" "+this.getUUID()+"]";
}
}
OrganizationNode.java:
#Entity
public class OrganizationNode extends AbstractEntity {
#ManyToOne(cascade=CascadeType.ALL)
NodeType nodeType;
#Column(nullable=true)
String name;
#OneToMany(cascade=CascadeType.ALL)
Set<OrganizationNode> children;
public OrganizationNode() {}
public OrganizationNode(NodeType nt, String name) {
this.nodeType = nt;
this.name = name;
children = new HashSet<>();
}
public void setNodeType(NodeType nt) {
nodeType = nt;
}
public NodeType getNodeType() {
return nodeType;
}
public String getName() {
if ((name == null) || (name.equals(""))) return null;
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<OrganizationNode> getChildren() {
return children;
}
public void setChildren(Set<OrganizationNode> children) {
this.children = children;
}
public void addNode(OrganizationNode node) {
children.add(node);
}
public void removeNode(OrganizationNode node) {
children.remove(node);
}
}
Device.java:
#Entity
public class Device extends OrganizationNode {
Set<Monitor> monitors;
public Device() {
super();
}
public Device(NodeType nt, String name) {
super(nt, name);
monitors = new HashSet<>();
}
public Set<Monitor> getMonitors() {
return monitors;
}
public void setMonitors(Set<Monitor> monitors) {
this.monitors = monitors;
}
public void addMonitor(Monitor monitor) {
monitors.add(monitor);
}
}
You need to decide what inheritance startegy you want to use.
The default one is typically the "Single Table Inheritance" so all the subclasses are represented in one table with merged columns.
#Inheritance
#Entity
public class OrganizationNode extends AbstractEntity {
...
}
and you saw it the sql.
You can have Joined, Multiple Table Inheritance where each subclass has its own table and are joined with parent table:
#Inheritance(strategy=InheritanceType.JOINED)
Finally, the last option is Table Per Class Inheritance, where there is no "inheritance" tree reflected in the tables structure, and each object has its full table with all the columns from the class and supperclasses.
#Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
The last one is the least efficient.
You can have only one strategy, which you define on the top of the inheritance (OrganizationNode), it cannot be changed in subclasses.
The default single table inheritance is typically the most efficient unless there are really a lot of columns which are not shared between the classes
You should probably explicitly declare column which will be used to deteriment the actual class type: #DiscriminatorColumn(name="NODE_TYPE") and for each Entity define the value: #DiscriminatorValue("TYPE1")
I'm facing a little problem with my web application which is in vaadin and i'm using jpa and eclipselink for the mapping. I have three entities :
encaiss (#MappedSuperclass contains just Id)
|
|
Encaissement (it contains the main and common properties)
/ \
/ \
Encaissement_Technique Encaissement_espece
When i create an entity "Encaissement" with "Espece" as type, it is well created in the table Encaissement but it doesn't exist in the table Encaissement_espece.
I guess that I should join the two tables according to the identifier (ID) which is in a #MappedSuperclass class. I would appreciate any help for managing my subordinate class (that is Encaissement_Technique and Encaissement_espece) because my next step would be to add records to those two tables from a simple form (so if i have a field "libelle" which is present in Encaissement but not in Encaissement_Espece how can make such instruction :
Encaissement_Espece espece= new Encaissement_Espece();
espece.setLibelle(field.getValue().toString());
Those are my entities :
encaiss, this class contain just the Id for all the classes
#MappedSuperclass
public abstract class encaiss {
#Id
#GeneratedValue(strategy=GenerationType.AUTO, generator="encaiss_seq_gen")
#SequenceGenerator(name="encaiss_seq_gen", sequenceName="ENCAISSEMENT_SEQ", allocationSize = 1, initialValue = 1)
protected Integer id_encaissement;
public Integer getId_encaissement() {
return id_encaissement;
}
public void setId_encaissement(Integer id_encaissement) {
this.id_encaissement = id_encaissement;
}
}
Encaissement (wich extend encaiss just to have an Id)
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="ENCAISS_TYPE")
#Table(name="ENCAISSEMENT")
public class Encaissement extends encaiss implements Serializable{
#ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
#JoinColumn(name = "ID_CLIENT")
private Client Client;
#Column(name="ENCAISS_TYPE")
protected String encaiss_type;
#Column(name="LIBELLE")
protected String libelle;
#Column(name="PIECE_JOINTE")
protected String piece_jointe;
#Embedded
protected Avis_Recette avis_recette;
public Encaissement(String encaiss_type, String libelle, String piece_jointe){
this.encaiss_type=encaiss_type;
this.libelle=libelle;
this.piece_jointe=piece_jointe;
}
public Encaissement(){
}
}
Encaissement_Espece, inherits from Encaissement
#Entity
#DiscriminatorValue("Espece")
#Table(name="ENCAISSEMENT_ESPECE")
public class Encaissement_Espece extends Encaissement{
public Caisse getCaisse() {
return caisse;
}
public void setCaisse(Caisse caisse) {
this.caisse = caisse;
}
public float getMontant() {
return montant;
}
public void setMontant(float montant) {
this.montant = montant;
}
#ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
#JoinColumn(name = "ID_CAISSE")
private Caisse caisse;
#Column(name = "MONTANT")
private float montant;
public Encaissement_Espece(float montant){
this.montant=montant;
}
public Encaissement_Espece(){
}
}
Encaissement_Technique, inherits from Encaissement
#Entity
#DiscriminatorValue("Technique")
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="ENCAISS_TECHNIQUE_TYPE")
#Table(name="ENCAISSEMENT_TECHNIQUE")
public class Encaissement_Technique extends Encaissement implements Serializable{
public Banque getBanque() {
return banque;
}
public void setBanque(Banque banque) {
this.banque = banque;
}
public float getPrimeCoass() {
return primeCoass;
}
public void setPrimeCoass(float primeCoass) {
this.primeCoass = primeCoass;
}
public Set<Periode> getPeriode() {
return periode;
}
public void setPeriode(Set<Periode> periode) {
this.periode = periode;
}
public String getEncaiss_technique_type() {
return encaiss_technique_type;
}
public void setEncaiss_technique_type(String encaiss_technique_type) {
this.encaiss_technique_type = encaiss_technique_type;
}
#Column(name="PRIMECOASS")
protected float primeCoass;
#Column(name="ENCAISS_TECHNIQUE_TYPE")
protected String encaiss_technique_type;
public Encaissement_Technique(float primeCoass, String encaiss_technique_type){
this.primeCoass=primeCoass;
this.encaiss_technique_type=encaiss_technique_type;
}
public Encaissement_Technique(){
}
}
I hope i will find a pertinent answer as i searched for this in vain. It'll help me a lot.
Thank you.
"When i create an entity "Encaissement" with "Espece" as type, it is well created in the table Encaissement but it doesn't exist in the table Encaissement_espece." This statement suggests you have an instance of Encaissement and expect JPA to turn it into an instance of Encaissement_Espece just by changing the encaiss_type value. Java object inheritance doesn't work that way, which is what JPA inheritance tries to map to a relational database. An object in java cannot change what it is simply by setting a flag - you need to create a new instance if you want the data represented differently.
In this case, you need to create an instance of the Encaissement_Espece class. Because this class maps to the Encaissement and Encaissement_espece tables, JPA will automatically insert a row into both to represent this object. When you create Encaissement instance, a row goes into the Encaissement table, while when you create Encaissement_Technique instances, a row goes into both Encaissement_Technique and Encaissement tables. If you wish to change the object's type once it is persisted, you need to remove the old instance, flush, then persist the new one.
As mentioned in another answer, the encaiss_type is controlled through the class type itself and so does not need a mapping. Having one might be handy for queries or access (though you can just use instance of etc); it should be marked as insertable=false, updatable=false so that you do not attempt to modify the value directly.
remove the
#Column(name="ENCAISS_TYPE")
protected String encaiss_type;
from the Encaissment.
It will be handle automatically by JPA. It should solve the problem.
I would like to put into db a class that have java.awt.geom.Point2D field. Is it possible?
Here is my code.
#Entity
#Table(name = "my_class_table")
public class MyClass {
private String aliasId;
private Point2D field;
public Point2D getField() {
return field;
}
public void setFieldPoint2D field) {
this.field = field;
}
public String getAliasId() {
return aliasId;
}
public void setAliasId(String aliasId) {
this.aliasId = aliasId;
}
}
And the reason of the exception which is thrown:
Could not determine type for: java.awt.geom.Point2D, at table: my_class_table, for columns: [org.hibernate.mapping.Column(field)]
Of course, the reason is quite obvious. My question is: how should I annotate the class to be able to use a field of Point2D class? Is it possible at all?
The simplest way is to use a java.awt.Point that extends Point2D and is a Serializable class. This way hibernate will automatically map it with SerializableType and you don't need to do anything more. The point object will be saved in its serialized form in a blob database table column.
You have also the option to define a custom hibernate type for the Point2D class. Here is a link of how to define a custom hibernate type.
You can't add annotations to existing classes.
But you can define a CompositeUserType to tell Hibernate how to map a Point2D.
Thanks guys for response. Unfortunatelly java.awt.Point class uses Integer, so it is useless in my case. The easiest way to solve it would be to use Point2D.Double which implements Serializable (but definition of UserType or CompositeUserType is more convenient if you don't want to change class definition). So, the simple solution:
#Entity
#Table(name = "my_class_table")
public class MyClass {
private String aliasId;
private Point2D.Double field;
public Point2D.Double getField() {
return field;
}
public void setField(Point2D.Double field) {
this.field = field;
}
public String getAliasId() {
return aliasId;
}
public void setAliasId(String aliasId) {
this.aliasId = aliasId;
}
}
But my final goal was to create a class with ordered list of points. If anybody is interested here is an example of the class representing line:
#Entity
public class Line {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idDb", unique = true, nullable = false)
private int id;
#ElementCollection
#CollectionTable(name="points_table", joinColumns = #JoinColumn(name="idDb"))
#IndexColumn(name = "idx")
#Column(name="point_val")
private List<Point2D.Double> points = new ArrayList<Point2D.Double>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<Point2D.Double> getPoints() {
return points;
}
public void setPoints(List<Point2D.Double> points) {
this.points = points;
}
}
Basic Hibernate question.
I have a class called Song and a class called Artwork, both exist independently. Then an instance of Song can contain multiple Artworks and when they do there are attribute particular to that relationship so I have created another class called CoverArt that links between the two. I'm using annotations for the hibernate stuff and having problems.
If I annotate all three classes as #Entity when I build the database I get the error >'org.hibernate.MappingException: Could not determine type for: Artwork, at table: CoverArt, for columns: [org.hibernate.mapping.Column(artwork)]'
If I change CoverArt to #Embeddable, as it only exists in the context of a Song I get the error
'org.hibernate.annotations.common.AssertionFailure: Declaring class is not found in the inheritance state hierarchy: com.jthink.songlayer.CoverArt'
I can't work out what these messages are saying, what I have wrong. Here is the relevant code from the three classes
Song:
#Entity
public class Song
{
#Id
#GeneratedValue
private Integer recNo;
#ElementCollection(fetch=FetchType.EAGER)
#IndexColumn(name = "POSITION")
private List<CoverArt> coverArt;
.....
CoverArt:
#Embeddable
public class CoverArt
{
private String imageType;
private String description;
private Artwork artwork;
#Id
#GeneratedValue
private Integer id;
public CoverArt()
{
}
public String getImageType()
{
return imageType;
}
public void setImageType(String imageType)
{
this.imageType = imageType;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public Artwork getArtwork()
{
return artwork;
}
public void setArtwork(Artwork artwork)
{
this.artwork = artwork;
}
}
Artwork:
#Entity
public class Artwork
{
public Artwork()
{
}
public Artwork(byte[] imageData)
{
this.imageData=imageData;
}
#Id
#GeneratedValue
private Integer id;
#Lob
private byte[] imageData;
private String mimeType;
private int width;
private int height;
public byte[] getImageData()
{
return imageData;
}
public void setImageData(byte[] imageData)
{
this.imageData = imageData;
}
public String getMimeType()
{
return mimeType;
}
public void setMimeType(String mimeType)
{
this.mimeType = mimeType;
}
public int getWidth()
{
return width;
}
public void setWidth(int width)
{
this.width = width;
}
public int getHeight()
{
return height;
}
public void setHeight(int height)
{
this.height = height;
}
}
The CoverArt class should be an entity.
The Song has a list of CoverArt instances, you should thus have
#OneToMany
#JoinColumn(...)
private List<CoverArt> coverArts; // note the final s, since it's plural
Each CoverArt links to an Artwork, so you should also have an association. It's not clear if it's a ManyToOne or a OneToOne, tough. I'll suppose it's a OneToOne:
#OneToOne
#JoinColumn(...)
private Artwork artwork;
It's pretty simple. Each time an entity has a reference to another entity, or a collection of another entity instances, you have an assosiation. And an association can be a OneToMany, OneToOne, ManyToOne or ManyToMany. You have to tell Hibernate which one it is. If you don't tell it, it assumes it's a simple Column which is wrong.
First of all You should tell us how do You want all that to look like in database.
I assume You want something like that:
table 'songs'
table 'artworks'
table 'cover_arts' with fkeys: song_id and artwork_id
So a Song "has many" CoverArts and each CoverArt "has one" Artwork.
If this is correct, then:
Annotate CoverArt with #Entity instead of #Embeddable
inside CoverArt class annotate field 'artwork' with #ManyToOne
replace #ElementCollection on field 'coverArt' inside Song class with #OneToMany. It would be nice to rename field 'coverArt' to 'coverArts' as it is a collection, not a single instance.
I am writing a webservice to maintain a database. I am trying to use JPA (EclipseLink) for the entity classes. However, the database uses natural primary keys and therefore there's potential that an update on the ID fields will fail due to foreign key constraints. Our DBA has provided a function to update the ID fields which will create a new parent record with the updated ID, update the child records to point to the new parent and delete the old parent.
If the ID fields could be updated "normally", I would have a situation like this:
#Entity
#Table(name = "PARENT")
public class Parent implements Serializable
{
private static final long serialVersionUID = 1L;
private String parent;
private String attribute;
private Set<Child> childs;
public Parent()
{
}
#Id
#Column(name = "PARENT")
public String getParent()
{
return this.parent;
}
public void setParent(String parent)
{
this.parent = parent;
}
#Column(name = "ATTRIBUTE")
public String getAttribute()
{
return this.attribute;
}
public void setAttribute(String attribute)
{
this.attribute = attribute;
}
#OneToMany(mappedBy = "parentBean")
public Set<Child> getChilds()
{
return this.childs;
}
public void setChilds(Set<Child> childs)
{
this.childs = childs;
}
}
#Entity
#Table(name = "CHILD")
public class Child implements Serializable
{
private static final long serialVersionUID = 1L;
private String child;
private String attribute;
private Parent parentBean;
public Child()
{
}
#Id
#Column(name = "CHILD")
public String getChild()
{
return this.child;
}
public void setChild(String child)
{
this.child = child;
}
#Column(name = "ATTRIBUTE")
public String getAttribute()
{
return this.attribute;
}
public void setAttribute(String attribute)
{
this.attribute = attribute;
}
#ManyToOne
#JoinColumn(name = "PARENT")
public Parent getParent()
{
return this.parent;
}
public void setParent(Parent parent)
{
this.parent = parent;
}
}
I also have a GenericServiceBean class with a method to call functions:
#Stateless
public class GenericServiceBean implements GenericService
{
#PersistenceContext(unitName = "PersistenceUnit")
EntityManager em;
public GenericServiceBean()
{
// empty
}
#Override
public <T> T create(T t)
{
em.persist(t);
return t;
}
#Override
public <T> void delete(T t)
{
t = em.merge(t);
em.remove(t);
}
#Override
public <T> T update(T t)
{
return em.merge(t);
}
#Override
public <T> T find(Class<T> type, Object id)
{
return em.find(type, id);
}
. . .
#Override
public String executeStoredFunctionWithNamedArguments(String functionName,
LinkedHashMap<String, String> namedArguments)
{
Session session = JpaHelper.getEntityManager(em).getServerSession();
StoredFunctionCall functionCall = new StoredFunctionCall();
functionCall.setProcedureName(functionName);
functionCall.setResult("RESULT", String.class);
for (String key : namedArguments.keySet())
{
functionCall.addNamedArgumentValue(key, namedArguments.get(key));
}
ValueReadQuery query = new ValueReadQuery();
query.setCall(functionCall);
String status = (String)session.executeQuery(query);
return status;
}
}
If I set the ID fields to be not editable:
#Id
#Column(name = "PARENT", udpatable=false)
public String getParent()
{
return this.parent;
}
and call parent.setParent(newParent) will this still update the ID in the entity object? How does this affect any child entities? Will they also be updated (or not)?
Another scenario I don't know how to deal with is where I need to update both the ID and another attribute. Should I call the function which updates (and commits) the ID in the database then make calls to set both the ID and attribute via the normal set* methods and then the persistence context will only commit the attribute change?
Perhaps this is a situation where JPA is not appropriate?
Any advice on this is greatly appreciated.
If I set the ID fields to be not editable (...) and call parent.setParent(newParent) will this still update the ID in the entity object? How does this affect any child entities? Will they also be updated (or not)?
updatable=false means that the column won't be part of the SQL UPDATE statement regardless of what you do at the object level so the Id shouldn't be updated. And I'm also tempted to say that child entities shouldn't be affected, especially since you're not cascading anything.
Another scenario I don't know how to deal with is where I need to update both the ID and another attribute (...)
Well, my understanding is that you'd have to call the function anyway so I would call it first.
Perhaps this is a situation where JPA is not appropriate?
I'm not sure raw SQL would deal better with your situation. Actually, the whole idea of changing primary keys sounds strange if I may.