2012-01-09 7 views
3

休止状態の関係に問題があります。n:m休止状態の追加情報との関係

シナリオ:2つのエンティティのタスクとリソースがあります。すべての「タスク」は複数の「リソース」を持つことができ、すべての「リソース」は複数の「タスク」を持つことができます。関係がn:m-関係であるように。リレーションテーブルでは、 'リソース'のタイプに対して追加の列が必要です。なぜなら、 'リソース'が持つことができる 'タスク'には異なる役割があるからです。

余計な列を持つ結合テーブルの例がいくつか見つかり、そのように実装しようとしました。例:http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/

問題: 「リソース」との関連付けを持つ「タスク」を削除すると、javax.persistence.EntityNotFoundException:削除されたエンティティがpersist:[...]にスローされます。

私の質問 このシナリオを処理する最善の方法は、「余分な列を持つテーブルを結合する」ですか?または、 'リソース'が持つことができるすべての役割に対して、単純な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; 
    } 
} 

Thxを

+0

エンティティ、この例外をスローするコード、および例外の完全なスタックトレースを表示します。 –

+0

希望のクラスは – Seffel

+0

です。タスクを削除すると、リソースも削除する必要がありますか? –

答えて

1

あなたはまだ削除されたエンティティへの参照を持っているようですね。たとえば、Taskオブジェクトを削除しますが、削除されたタスクを参照するTaskResourceオブジェクトはまだ存在します。

これが問題の場合は、タスクを削除した後に、taskResource.setTaskFk(null)のようなものを試して、抱擁の参照を削除することができます。

+0

あなたは正しい方法で私を連れて来ました:)。私はすべてのFk-Referencesを明示的にnullに設定し、それが解決策でした。どうも – Seffel