n: m Связь с дополнительной информацией в Hibernate - PullRequest
3 голосов
/ 09 января 2012

У меня проблема с отношениями в Hibernate.

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

Я нашел несколько примеров таблицы соединений с дополнительным столбцом и попытался реализовать ее таким образом.Пример: 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;
  }
}

Thx

1 Ответ

1 голос
/ 10 января 2012

Похоже, у вас все еще есть ссылки на удаленную сущность.Например, вы удаляете объект Task, но все еще существует объект TaskResource, который ссылается на удаленную задачу.

Если это проблема, то после удаления Задачи вы можете попробовать что-то вроде taskResource.setTaskFk(null), чтобы удалить висящую ссылку.

...