Hallo Leute,
ich haenge jetzt schon seit mehr als 2 tagen an diesem problem und bekomms einfach nicht hin.
ich hab 2 (bzw. eigentlich 3 aber das is ned so wichtig) tabellen wobei ich eine n:m relation abbilde aber dafuer keine 3. tabelle verwende sondern absichltich die 3. normalform verletze.
1. tabelle
JakeObject(
objectid char(36) primary key,
ein paar andere werte
);
2. tabelle
tag (
name varchar(255),
objectId char(36) references jakeObject(objectid),
primary key(objectid, name)
);
so sollte es sein. wir haben absichtlich keine automatische id in tag, da mehrere clients unabhaengig voneinander ein gleiches tag objekt nur mit der info "name" und "objektid" erstellen koennen muessen.
Hibernate version:
Code:
<hibernate-annotations.version>3.4.0.GA</hibernate-annotations.version>
<hibernate-commons-annotations.version>3.3.0.ga</hibernate-commons-annotations.version>
<hibernate-core.version>3.3.1.GA</hibernate-core.version>
Mapping documents:Annotations
Code between sessionFactory.openSession() and session.close():Code:
public class HibernateJakeObjectDao implements IJakeObjectDao
{
....
public T addTagTo(T jakeObject, Tag tag) {
log.debug("Adding object "+ jakeObject + " to tag " + tag);
tag.setObject(jakeObject);
log.debug("persisting tag");
this.getHibernateTemplate().getSessionFactory().getCurrentSession().persist(tag);
return jakeObject;
}
public List<Tag> getTagsFor(T jakeObject) {
List<Tag> results = this.getHibernateTemplate().getSessionFactory().getCurrentSession().
createQuery("FROM tag WHERE objectId = ? ").setString(0, jakeObject.getUuid().toString()).list();
//createCriteria(Tag.class).createCriteria("object", jakeObject.getUuid().toString()).list();
//createQuery("FROM Tag WHERE jakeObject = ? ").setEntity(0, jakeObject).list();
return results;
}
public void removeTagsFrom(T jakeObject, Tag... tags) {
for(Tag t : tags)
{
// t.setObject(jakeObject);
int result = this.getHibernateTemplate().getSessionFactory().getCurrentSession().
// createQuery("DELETE FROM tag WHERE text = ? AND objectid = ? ").
createSQLQuery("DELETE FROM tag WHERE text = ? AND objectid = ? ").
setString(0, t.getName()).setString(1, jakeObject.getUuid().toString()).executeUpdate();
log.debug("result: " + result);
}
}
}
Full stack trace of any exception that occurs:[Jake-Core] [main] [DEBUG] dao.HibernateNoteObjectDaoTest.testRemoveTagsFrom:202 - ==========================
[Jake-Core] [main] [DEBUG] dao.HibernateJakeObjectDao.addTagTo:108 - Adding object com.jakeapp.core.domain.NoteObject@34139259 to tag test1
[Jake-Core] [main] [DEBUG] dao.HibernateJakeObjectDao.addTagTo:111 - persisting tag
[Jake-Core] [main] [DEBUG] dao.HibernateJakeObjectDao.addTagTo:108 - Adding object com.jakeapp.core.domain.NoteObject@34139259 to tag test2
[Jake-Core] [main] [DEBUG] dao.HibernateJakeObjectDao.addTagTo:111 - persisting tag
[Jake-Core] [main] [DEBUG] dao.HibernateJakeObjectDao.addTagTo:108 - Adding object com.jakeapp.core.domain.NoteObject@34139259 to tag test4
[Jake-Core] [main] [DEBUG] dao.HibernateJakeObjectDao.addTagTo:111 - persisting tag
[Jake-Core] [main] [DEBUG] dao.HibernateJakeObjectDao.addTagTo:108 - Adding object com.jakeapp.core.domain.NoteObject@34139259 to tag test4
[Jake-Core] [main] [DEBUG] dao.HibernateJakeObjectDao.addTagTo:111 - persisting tag
Hibernate: insert into jakeobject (deleted, modified, objectId) values (?, ?, ?)
Hibernate: insert into note (text, objectId) values (?, ?)
Hibernate: insert into tag (objectid, text) values (?, ?)
Hibernate: insert into tag (objectid, text) values (?, ?)
[Jake-Core] [main] [WARN] util.JDBCExceptionReporter.logExceptions:100 - SQL Error: -104, SQLState: 23000
[Jake-Core] [main] [ERROR] util.JDBCExceptionReporter.logExceptions:101 - Unique constraint violation: in statement [insert into tag (objectid, text) values (?, ?)]
[Jake-Core] [main] [ERROR] def.AbstractFlushingEventListener.performExecutions:324 - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: could not insert: [com.jakeapp.core.domain.Tag]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2295)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2688)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at com.jakeapp.core.dao.HibernateNoteObjectDaoTest.tearDown(HibernateNoteObjectDaoTest.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.test.context.junit4.SpringMethodRoadie.runAfters(SpringMethodRoadie.java:340)
at org.springframework.test.context.junit4.SpringMethodRoadie.runBeforesThenTestThenAfters(SpringMethodRoadie.java:262)
at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:234)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:204)
at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:146)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:151)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:338)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:997)
Caused by: java.sql.SQLException: Unique constraint violation: in statement [insert into tag (objectid, text) values (?, ?)]
at org.hsqldb.jdbc.Util.throwError(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.executeUpdate(Unknown Source)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:46)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2275)
... 36 more
Name and version of the database you are using:hsqldb 1.8.0.1
The generated SQL (show_sql=true):CREATE MEMORY TABLE JAKEOBJECT(OBJECTID CHAR(36) NOT NULL PRIMARY KEY,DELETED BOOLEAN,MODIFIED BOOLEAN)
CREATE MEMORY TABLE TAG(TEXT VARCHAR(255) NOT NULL PRIMARY KEY,OBJECTID CHAR(36) NOT NULL)
-- hier liegt das problem, das create table sollte eigentlich so aussehen:
-- CREATE TABLE tag ( objectId CHAR(36) NOT NULL, text VARCHAR(255) NOT NULL, PRIMARY KEY (objectId, text), FOREIGN KEY (objectId) REFERENCES jakeobject(objectId) );
Debug level Hibernate log excerpt:sorry, weiss nicht was man hier will.
hier noch die klassen. JakeObject ist meiner Meinung nach korrekt, immerhin gehen bis auf die tags alle dinge
Code:
@Entity(name = "jakeobject")
@Embeddable
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class JakeObject implements ILogable {
private static final long serialVersionUID = -3601181472574035652L;
@Id
private UUID uuid;
private Project project;
private boolean deleted;
private boolean modified;
/**
* Default ctor.
*/
public JakeObject() {
// default ctor for hibernate
}
/**
* Construct a new <code>JakeObject</code>.
* @param uuid the <code>uuid</code> of the <code>JakeObject</code>
* @param project the <code>Project</code> that is associated with the
* <code>JakeObject</code>
* @throws IllegalArgumentException if uuid was not valid
* @see JakeObject#setUuid(UUID)
*/
protected JakeObject(UUID uuid, Project project) throws
IllegalArgumentException {
this.setUuid(uuid);
this.setProject(project);
}
/**
* Get the <code>uuid</code>.
* @return the <code>uuid</code> of the <code>JakeObject</code>
*/
@Transient
public UUID getUuid() {
return this.uuid;
}
@Id
@Column(name = "objectId", unique = true)
private String getUuidString()
{
return this.uuid.toString();
}
private void setUuidString(String uuid)
{
this.uuid = UUID.fromString(uuid);
}
/**
* Get the associated <code>project</code>.
* @return the project that is associated with the <code>JakeObject</code>
* @throws IllegalArgumentException if null is supplied
*/
@Transient
public Project getProject() throws IllegalArgumentException {
return this.project;
}
/**
* Sets the UUID of this JakeObject to the given uuid object.
* @param uuid the uuid to be set
* @throws IllegalArgumentException if null is supplied for
* <code>uuid</code>
*/
protected void setUuid(UUID uuid) throws IllegalArgumentException {
if (uuid == null) {
throw new IllegalArgumentException();
}
this.uuid = uuid;
}
protected void setProject(Project project) {
this.project = project;
}
@Column(name = "deleted")
public boolean isDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
@Column(name = "modified")
public boolean isModified() {
return modified;
}
public void setModified(boolean modified) {
this.modified = modified;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof JakeObject)) return false;
JakeObject that = (JakeObject) o;
if (deleted != that.deleted) return false;
if (modified != that.modified) return false;
if (!uuid.equals(that.uuid)) return false;
return true;
}
@Override
public int hashCode() {
int result = uuid.hashCode();
result = 31 * result + (deleted ? 1 : 0);
result = 31 * result + (modified ? 1 : 0);
return result;
}
}
hier das problemkind
Code:
import javax.persistence.*;
import javax.persistence.Entity;
import com.jakeapp.core.domain.exceptions.InvalidTagNameException;
import org.hibernate.annotations.*;
/**
* A simple tag. It only consists of a <code>name</code>.
*/
@Entity(name = "tag")
//@Table(name = "tag")
//@SecondaryTable(name = "jakeobject", pkJoinColumns = @PrimaryKeyJoinColumn(name = "objectid", columnDefinition = "char(36"))
//@Embeddable
//@UniqueConstraint(columnNames = {"objectid", "text"})
//@PrimaryKeyJoinColumns(value = {@PrimaryKeyJoinColumn(name = "text"), @PrimaryKeyJoinColumn(name="objectid") } )
public class Tag implements ILogable {
private static final long serialVersionUID = -2201488676480921149L;
private JakeObject jakeObject;
private String name;
/**
* Construct a new Tag.
*
* @param name the name of the tag to be created
* @throws InvalidTagNameException if the name is not valid
* @see #setName(String)
*/
public Tag(String name) throws InvalidTagNameException {
super();
this.setName(name);
}
/**
* Get the name of the tag.
*
* @return the name of the tag
*/
// @NaturalId (mutable = true)
// @Id
// @NaturalId
@Id
@Column(name = "text")
public String getName() {
return this.name;
}
/**
* Set the name of the <code>tag</code>.
*
* @param name the new name of the tag. It must not contain a
* whitespace-character.
* @throws InvalidTagNameException Raised if the <code>name</code> contains
* a whitespace-character
*/
public void setName(String name) throws InvalidTagNameException {
if (name.matches(".*\\s.*")) {
throw new InvalidTagNameException(
"A Tag may not contain a whitespace");
}
this.name = name;
}
// @OneToOne
// @EmbeddedId
// @ManyToMany
// @EmbeddedId
//@IdClass(value = JakeObject.class)
// @Id
// @NaturalId (mutable = false)
// @NaturalId
@Embedded
// @Column(name = "objectid", columnDefinition = "char(36)")
// @ForeignKey(name = "FK_JAKEOBJECT")
// @Column(name = "objectid", columnDefinition = "char(36")
// @JoinColumn(name = "objectid", columnDefinition = "char(36)", nullable = false, table = "tag")
@ManyToOne(optional = false, targetEntity = JakeObject.class)
@JoinColumn(name = "objectid", columnDefinition = "char(36)", nullable = false)
public JakeObject getObject() {
return this.jakeObject;
}
public void setObject(JakeObject object) {
this.jakeObject = object;
}
/**
* Test if two <code>tag</code>s are equal.
*
* @param obj The object to compare this object to.
* @return <code>true</code> iff the <code>name</code>s are equal.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tag tag = (Tag) o;
if (jakeObject != null ? !jakeObject.equals(tag.jakeObject) : tag.jakeObject != null) return false;
if (!name.equals(tag.name)) return false;
return true;
}
@Override
public int hashCode() {
int result = jakeObject != null ? jakeObject.hashCode() : 0;
result = 31 * result + name.hashCode();
return result;
}
/**
* Returns the string representation of the <code>tag</code>.
*
* @return the name of the tag.
*/
@Override
public String toString() {
return this.name;
}
}
Wie man sieht, schaff ichs einfach nicht, dass er das feld name UND object als primary key hernimmt.
Bitte bitte, ich brauch da wirklich hilfe.. hab da jetzt schon alles ausprobiert wo ich dachte es koennte so gehn, aber scheinbar stell ich mich zu bloed dafuer an.
vielen vielen dank,
Falls ihr noch weitere infos braucht, bitte einfach reply posten, ich werd das sofort nachreichen!
dominik