Warum wird ConstraintException in den Ruhezustand versetzt, als würde versucht, ein Objekt zu erstellen, wenn bereits eines vorhanden ist?
Ich verwende saveOrUpdate () beim Aktualisieren / Erstellen eines CoverImage-Objekts. Sehr gelegentlich erhalte ich eine Einschränkungsverletzung für den Primärschlüssel.
org.hibernate.exception.ConstraintViolationException:
Unique index or primary key violation: "PRIMARY_KEY_6
ON PUBLIC.COVERIMAGE(DATAKEY)"; SQL statement:
Anscheinend wird versucht, ein neues CoverImage (INSERT) zu erstellen, anstatt ein vorhandenes CoverImage (UPDATE) zu aktualisieren, aber ich weiß nicht warum, da datakey als @id der Klasse definiert ist und ich das datakey einstelle.
Ich verwende saveOrUpdate (), anstatt separate Teile für save () und update () zu haben, da der Code mehrere Threads enthält. Ich überprüfe tatsächlich die Existenz der Instanz, bevor ich diese Methode aufrufe, und rufe nur auf, wenn das Objekt nicht vorhanden ist, sodass ich nicht erwarte, dass es bereits vorhanden ist, aber es besteht immer die Möglichkeit, dass dies der Fall ist. Das Problem scheint ungefähr 1 in 3000 mal aufzutreten.
Hier ist die Hibernate-Klasse
package com.jthink.songlayer;
import com.jthink.songlayer.utils.Base64Coder;
import org.hibernate.annotations.IndexColumn;
import org.hibernate.envers.Audited;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.stream.ImageInputStream;
import javax.persistence.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* An Image
*/
@Audited
@Entity
public class CoverImage
{
public CoverImage()
{
}
public CoverImage(byte[] imageData)
{
this.imageData=imageData;
}
@Id
@Column(length = 1000)
private String dataKey;
@Version
private int version;
public String getDataKey()
{
return dataKey;
}
public void setDataKey(String dataKey)
{
this.dataKey = dataKey;
}
@Lob
private byte[] imageData;
@Lob
private byte[] thumbnailData;
private String mimeType;
private int width;
private int height;
private boolean isLinked;
@org.hibernate.annotations.Index(name = "IDX_SOURCE")
private String source;
@Lob
private byte[] resizedImageData;
private int resizedWidth;
private int resizedHeight;
public byte[] getImageData()
{
return imageData;
}
public void setImageData(byte[] imageData)
{
this.imageData = imageData;
}
public byte[] getThumbnailData()
{
return thumbnailData;
}
public void setThumbnailData(byte[] thumbnailData)
{
this.thumbnailData = thumbnailData;
}
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;
}
public boolean isLinked()
{
return isLinked;
}
public void setLinked(boolean linked)
{
isLinked = linked;
}
public String getSource()
{
return source;
}
public void setSource(String source)
{
this.source = source;
}
public byte[] getResizedImageData()
{
return resizedImageData;
}
public void setResizedImageData(byte[] resizedImageData)
{
this.resizedImageData = resizedImageData;
}
public int getResizedWidth()
{
return resizedWidth;
}
public void setResizedWidth(int resizedWidth)
{
this.resizedWidth = resizedWidth;
}
public int getResizedHeight()
{
return resizedHeight;
}
public void setResizedHeight(int resizedHeight)
{
this.resizedHeight = resizedHeight;
}
/**
* Create message digest of the byte data
* <p/>
* This uniquely identifies the imagedata, but takes up much less room than the original data
*
* @param imageData
* @return
*/
public static byte[] getImageDataDigest(byte[] imageData)
{
//Calculate checksum
MessageDigest md;
try
{
md = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException nsae)
{
//This should never happen
throw new RuntimeException(nsae);
}
md.reset();
md.update(imageData);
return md.digest();
}
public static String createKeyFromData(byte[] imageData)
{
try
{
String base64key = CharBuffer.wrap(Base64Coder.encode(getImageDataDigest(imageData))).toString();
return base64key;
}
catch (NullPointerException npe)
{
throw new RuntimeException("Unable to create filename from sum");
}
}
}
und das ist der Code, der es verwendet
try
{
//Create thumbnail
BufferedImage thumb = ArtworkHelper.resizeToThumbnail(newBuffered, THUMBNAIL_SIZE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(thumb, ImageFormats.V22_JPG_FORMAT.toLowerCase(), baos);
session = com.jthink.songlayer.hibernate.HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
coverImage = new CoverImage(imageData);
coverImage.setThumbnailData(baos.toByteArray());
coverImage.setDataKey(CoverImage.createKeyFromData(imageData));
coverImage.setSource(source);
coverImage.setWidth(newBuffered.getWidth());
coverImage.setHeight(newBuffered.getHeight());
coverImage.setMimeType(ImageFormats.getMimeTypeForBinarySignature(imageData));
session.saveOrUpdate(coverImage);
tx.commit();
return coverImage;
}
catch(IOException ioe)
{
MainWindow.logger.log(Level.SEVERE, "Failed Creating Thumbnails" + ioe.getMessage(), ioe);
return null;
}
catch(StaleObjectStateException sose)
{
return SongCache.findCoverImageBySourceInOwnSession(source);
}
finally
{
HibernateUtil.closeSession(session);
}
Vollständiger Stack-Trace
10/01/2013 09.17.12:com.jthink.songkong.analyse.analyser.DiscogsSongGroupMatcher:call:SEVERE: Failed AddSongToDatabase:Unique index or primary key violation: "PRIMARY_KEY_6 ON PUBLIC.COVERIMAGE(DATAKEY)"; SQL statement:
insert into CoverImage (height, imageData, isLinked, mimeType, resizedHeight, resizedImageData, resizedWidth, source, version, width, dataKey) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23505-166]
org.hibernate.exception.ConstraintViolationException: Unique index or primary key violation: "PRIMARY_KEY_6 ON PUBLIC.COVERIMAGE(DATAKEY)"; SQL statement:
insert into CoverImage (height, imageData, isLinked, mimeType, resizedHeight, resizedImageData, resizedWidth, source, version, width, dataKey) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23505-166]
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:128)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at $Proxy27.executeUpdate(Unknown Source)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2962)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3403)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1210)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:399)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at com.jthink.songkong.db.SongCache.saveNewCoverImage(SongCache.java:332)