2012-01-09 2 views
3

У меня возникла проблема с отношениями в Hibernate.n: m Связь с дополнительной информацией в Hibernate

Сценарий: у меня есть 2 объекта «Задача» и «Ресурс». Каждая «задача» может иметь несколько «ресурсов», а каждый «ресурс» может иметь несколько «задач». Таким образом, отношение является n: m-Relation. В таблице отношений мне нужен дополнительный столбец для типа «Ресурс», потому что в «Задаче» есть разные роли, которые может иметь «Ресурс».

Я нашел несколько примеров для соединения таблицы с дополнительным столбцом и попытался реализовать ее таким образом. Пример: http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/

Проблема: При удалении «Task», который имеет связь с «Ресурс» javax.persistence.EntityNotFoundException: удаленный объект передается сохраняются: [...] отбрасывается.

Теперь мой вопрос: Является ли «join table with extra column» лучшим способом справиться с этим сценарием? Или лучше использовать простые отношения 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

Смежные вопросы