n:m 与 Hibernate 中附加信息的关系
我在 Hibernate 中遇到了关系问题。
场景:我有 2 个实体“任务”和“资源”。每个“任务”可以有多个“资源”,每个“资源”可以有多个“任务”。因此该关系是 an:m-Relation。在关系表中,我需要为“资源”类型添加一个附加列,因为“资源”在“任务”中可以具有不同的角色。
我找到了一些带有额外列的连接表的示例,并尝试以这种方式实现它。示例: http:// www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/
问题: 当我删除与“资源”关联的“任务”时,抛出 javax.persistence.EntityNotFoundException:已删除实体传递给持久:[...]。
现在我的问题是: “使用额外列连接表”是处理这种情况的最佳方法吗?或者对于“资源”可以拥有的每个角色使用简单的 ManyToMany(@JoinTable) 关系是否更好?
例如:当有 4 个角色时,“任务”和“资源”之间将有 4 个不同的关系表。
出现以下异常的原因可能是什么?
‘javax.persistence.EntityNotFoundException: deleted entity passed to persist: […]’
编辑:
deleted entity passed to persist: [com.domain.Task# ]
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1369)
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1315)
org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:81)
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
$Proxy43.deleteVorgaenge(Unknown Source)
com.service.locklayers.TaskLockService.deleteTasks(TaskLockService.java:364)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:303)
sun.rmi.transport.Transport$1.run(Transport.java:159)
java.security.AccessController.doPrivileged(Native Method)
sun.rmi.transport.Transport.serviceCall(Transport.java:155)
sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
java.lang.Thread.run(Thread.java:662)
以下是涉及的课程...
@Entity
@Table( name = "task" )
public class Task implements Serializable
{
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "task_id" )
private int taskId;
private String name;
@OneToMany( fetch = FetchType.EAGER, mappedBy = "taskFk", cascade = CascadeType.ALL )
Set<TaskZuResource> taskZuResourceList = new HashSet<TaskZuResource>();
public int getId()
{
return taskId;
}
}
@Entity
@Table( name = "resource" )
public class Resource implements Serializable
{
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "resource_id" )
private int resourceId;
private String name;
@OneToMany( mappedBy = "resourceFk", fetch = FetchType.EAGER, cascade = CascadeType.ALL )
Set<TaskZuResource> taskZuResourceList = new HashSet<TaskZuResource>();
public int getId()
{
return resourceId;
}
}
@Entity
@Table( name = "task_zu_resource" )
public class TaskZuResource implements Serializable
{
@EmbeddedId
private TaskZuResourceId pk;
@MapsId( "taskFk" )
@ManyToOne( optional = false, fetch = FetchType.EAGER )
@JoinColumn( name = "task_fk" )
private Task taskFk;
@MapsId( "resourceFk" )
@ManyToOne( optional = false, fetch = FetchType.EAGER )
@JoinColumn( name = "resource_fk" )
private Resource resourceFk;
public TaskZuResource()
{
}
public TaskZuResource( Task taskFk, Resource resourceFk, int resourcenArt )
{
this.taskFk = taskFk;
this.resourceFk = resourceFk;
pk = new TaskZuResourceId( taskFk.getId(), resourceFk.getId(), resourcenArt );
}
public TaskZuResourceId getPk()
{
return pk;
}
public void setPk( TaskZuResourceId pk )
{
this.pk = pk;
}
public Task getTaskFk()
{
return taskFk;
}
public void setTaskFk( Task taskFk )
{
this.taskFk = taskFk;
}
public Resource getResourceFk()
{
return resourceFk;
}
public void setResourceFk( Resource resourceFk )
{
this.resourceFk = resourceFk;
}
@Transient
public int getResourcenType()
{
return getPk().getResourcenType();
}
public void setResourcenType( int resourcenArt )
{
getPk().setResourcenType( resourcenArt );
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((pk == null) ? 0 : pk.hashCode());
result = prime * result + ((resourceFk == null) ? 0 : resourceFk.hashCode());
result = prime * result + ((taskFk == null) ? 0 : taskFk.hashCode());
return result;
}
@Override
public boolean equals( Object obj )
{
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( getClass() != obj.getClass() )
return false;
TaskZuResource other = (TaskZuResource) obj;
if ( pk == null )
{
if ( other.pk != null )
return false;
}
else
if ( !pk.equals( other.pk ) )
return false;
if ( resourceFk == null )
{
if ( other.resourceFk != null )
return false;
}
else
if ( !resourceFk.equals( other.resourceFk ) )
return false;
if ( taskFk == null )
{
if ( other.taskFk != null )
return false;
}
else
if ( !taskFk.equals( other.taskFk ) )
return false;
return true;
}
}
@Embeddable
public class TaskZuResourceId implements Serializable
{
private int taskFk;
private int resourceFk;
@Column( name = "resourcen_type" )
private int resourcenType;
public TaskZuResourceId()
{
}
public TaskZuResourceId( int taskFk, int resourceFk, int resourcenType )
{
this.taskFk = taskFk;
this.resourceFk = resourceFk;
this.resourcenType = resourcenType;
}
public int getTaskFk()
{
return taskFk;
}
public void setTaskFk( int taskFk )
{
this.taskFk = taskFk;
}
public int getResourceFk()
{
return resourceFk;
}
public void setResourceFk( int resourceFk )
{
this.resourceFk = resourceFk;
}
public int getResourcenType()
{
return resourcenType;
}
public void setResourcenType( int resourcenType )
{
this.resourcenType = resourcenType;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + resourceFk;
result = prime * result + resourcenType;
result = prime * result + taskFk;
return result;
}
@Override
public boolean equals( Object obj )
{
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( getClass() != obj.getClass() )
return false;
TaskZuResourceId other = (TaskZuResourceId) obj;
if ( resourceFk != other.resourceFk )
return false;
if ( resourcenType != other.resourcenType )
return false;
if ( taskFk != other.taskFk )
return false;
return true;
}
}
谢谢
I got a problem with relations in Hibernate.
Scenario: I got 2 Entities ‘Task’ and ‘Resource’. Every ‘Task’ can have multiple ‘Resource’s and every ‘Resource’ can have multiple ‘Task’s. So that the relation is a n:m-Relation. In the relation table I need an additional column for the type of ‘Resource’ because there are different roles in the ‘Task’ that the ‘Resource’ can have.
I found some examples for join table with extra column and tried to implement it that way. Example: http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/
The problem:
When I delete a ‘Task‘ that has an association with ‘Resource’ an javax.persistence.EntityNotFoundException: deleted entity passed to persist: […] is thrown.
Now my question:
Is the ‘join table with extra column’ the best way handle this scenario? Or is it better to use simple ManyToMany(@JoinTable) Relations for every role that the ‘Resource’ can have?
For example: When there are 4 roles there would be 4 different relation tables between ‘Task’ and ‘Resource’.
What can be the reason for the following exception?
‘javax.persistence.EntityNotFoundException: deleted entity passed to persist: […]’
Edited:
deleted entity passed to persist: [com.domain.Task# ]
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1369)
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1315)
org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:81)
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
$Proxy43.deleteVorgaenge(Unknown Source)
com.service.locklayers.TaskLockService.deleteTasks(TaskLockService.java:364)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:303)
sun.rmi.transport.Transport$1.run(Transport.java:159)
java.security.AccessController.doPrivileged(Native Method)
sun.rmi.transport.Transport.serviceCall(Transport.java:155)
sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
java.lang.Thread.run(Thread.java:662)
Here are the involved Classes...
@Entity
@Table( name = "task" )
public class Task implements Serializable
{
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "task_id" )
private int taskId;
private String name;
@OneToMany( fetch = FetchType.EAGER, mappedBy = "taskFk", cascade = CascadeType.ALL )
Set<TaskZuResource> taskZuResourceList = new HashSet<TaskZuResource>();
public int getId()
{
return taskId;
}
}
@Entity
@Table( name = "resource" )
public class Resource implements Serializable
{
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "resource_id" )
private int resourceId;
private String name;
@OneToMany( mappedBy = "resourceFk", fetch = FetchType.EAGER, cascade = CascadeType.ALL )
Set<TaskZuResource> taskZuResourceList = new HashSet<TaskZuResource>();
public int getId()
{
return resourceId;
}
}
@Entity
@Table( name = "task_zu_resource" )
public class TaskZuResource implements Serializable
{
@EmbeddedId
private TaskZuResourceId pk;
@MapsId( "taskFk" )
@ManyToOne( optional = false, fetch = FetchType.EAGER )
@JoinColumn( name = "task_fk" )
private Task taskFk;
@MapsId( "resourceFk" )
@ManyToOne( optional = false, fetch = FetchType.EAGER )
@JoinColumn( name = "resource_fk" )
private Resource resourceFk;
public TaskZuResource()
{
}
public TaskZuResource( Task taskFk, Resource resourceFk, int resourcenArt )
{
this.taskFk = taskFk;
this.resourceFk = resourceFk;
pk = new TaskZuResourceId( taskFk.getId(), resourceFk.getId(), resourcenArt );
}
public TaskZuResourceId getPk()
{
return pk;
}
public void setPk( TaskZuResourceId pk )
{
this.pk = pk;
}
public Task getTaskFk()
{
return taskFk;
}
public void setTaskFk( Task taskFk )
{
this.taskFk = taskFk;
}
public Resource getResourceFk()
{
return resourceFk;
}
public void setResourceFk( Resource resourceFk )
{
this.resourceFk = resourceFk;
}
@Transient
public int getResourcenType()
{
return getPk().getResourcenType();
}
public void setResourcenType( int resourcenArt )
{
getPk().setResourcenType( resourcenArt );
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((pk == null) ? 0 : pk.hashCode());
result = prime * result + ((resourceFk == null) ? 0 : resourceFk.hashCode());
result = prime * result + ((taskFk == null) ? 0 : taskFk.hashCode());
return result;
}
@Override
public boolean equals( Object obj )
{
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( getClass() != obj.getClass() )
return false;
TaskZuResource other = (TaskZuResource) obj;
if ( pk == null )
{
if ( other.pk != null )
return false;
}
else
if ( !pk.equals( other.pk ) )
return false;
if ( resourceFk == null )
{
if ( other.resourceFk != null )
return false;
}
else
if ( !resourceFk.equals( other.resourceFk ) )
return false;
if ( taskFk == null )
{
if ( other.taskFk != null )
return false;
}
else
if ( !taskFk.equals( other.taskFk ) )
return false;
return true;
}
}
@Embeddable
public class TaskZuResourceId implements Serializable
{
private int taskFk;
private int resourceFk;
@Column( name = "resourcen_type" )
private int resourcenType;
public TaskZuResourceId()
{
}
public TaskZuResourceId( int taskFk, int resourceFk, int resourcenType )
{
this.taskFk = taskFk;
this.resourceFk = resourceFk;
this.resourcenType = resourcenType;
}
public int getTaskFk()
{
return taskFk;
}
public void setTaskFk( int taskFk )
{
this.taskFk = taskFk;
}
public int getResourceFk()
{
return resourceFk;
}
public void setResourceFk( int resourceFk )
{
this.resourceFk = resourceFk;
}
public int getResourcenType()
{
return resourcenType;
}
public void setResourcenType( int resourcenType )
{
this.resourcenType = resourcenType;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + resourceFk;
result = prime * result + resourcenType;
result = prime * result + taskFk;
return result;
}
@Override
public boolean equals( Object obj )
{
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( getClass() != obj.getClass() )
return false;
TaskZuResourceId other = (TaskZuResourceId) obj;
if ( resourceFk != other.resourceFk )
return false;
if ( resourcenType != other.resourcenType )
return false;
if ( taskFk != other.taskFk )
return false;
return true;
}
}
Thx
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
听起来您仍然引用已删除的实体。例如,您删除了一个 Task 对象,但仍然有一个 TaskResource 对象引用已删除的任务。
如果这是问题所在,那么在删除任务后,您可以尝试使用
taskResource.setTaskFk(null)
之类的方法来删除悬空引用。It sounds like you still have references to a deleted entity. For example, you delete a Task object, but there is still a TaskResource object that references the deleted task.
If this is the problem, then after you delete the Task you can try something like
taskResource.setTaskFk(null)
to remove the dangling reference.