Hibernate - 如何正确删除父级

时间:2014-11-03 18:21:02

标签: java hibernate

好的,所以我想实现一个简单的论坛示例。所以,我有线程,消息和用户,当然这些是pojos(我省略了通常的getter和简单)

消息

@Entity
@Table(name = "message")
public class Message implements java.io.Serializable, RecognizedServerEntities
{       
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @Cascade({ CascadeType.SAVE_UPDATE })
    @JoinColumn(name = "thread", nullable = false)
    private Thread thread;

    @ManyToOne(fetch = FetchType.LAZY)
    @Cascade({ CascadeType.SAVE_UPDATE })
    @JoinColumn(name = "author", nullable = true)
    private User user;

    @Column(name = "title", nullable = false, length = 31)
    private String title;

    @Column(name = "body", nullable = false, columnDefinition = "Text")
    private String body;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "last_modified_date", nullable = false, length = 19)
    private Date lastModifiedDate;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_date", nullable = false, updatable = false, length = 19)
    private Date createdDate;
}

用户

@Entity
@Table(name = "user", uniqueConstraints =
{ @UniqueConstraint(columnNames = "email"),
    @UniqueConstraint(columnNames = "nick") })
public class User implements java.io.Serializable, RecognizedServerEntities
{
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @Column(name = "email", unique = true, nullable = false, length = 31)
    private String email;

    @Column(name = "password", nullable = false, length = 31)
    private String password;

    @Column(name = "nick", unique = true, nullable = false, length = 31)
    @NaturalId(mutable = false)
    private String nick;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "registered_date", nullable = false, updatable = false, length = 19)
    private Date registeredDate;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", orphanRemoval = false)
    private Set<Thread> threads = new HashSet<Thread>(0);

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", orphanRemoval = false)
    private /**transient /**/ Set<Message> messages = new HashSet<Message>(0);
}

@Entity
@Table(name = "thread")
public class Thread implements java.io.Serializable, RecognizedServerEntities
{
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @Cascade({CascadeType.SAVE_UPDATE})
    @JoinColumn(name = "parent_thread", nullable = true)
    private Thread parentThread;

    @ManyToOne(fetch = FetchType.LAZY)
    @Cascade({CascadeType.SAVE_UPDATE})
    @JoinColumn(name = "author", nullable = true)
    private User user;

    @Column(name = "title", nullable = false, length = 63)
    private String title;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "last_modified_date", nullable = false, length = 19)
    private Date lastModifiedDate;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_date", nullable = false, updatable = false, length = 19)
    private Date createdDate;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "thread"/**/, orphanRemoval = true/**/)
    @Cascade({ CascadeType.REMOVE })
    private /**transient /**/ Set<Message> messages = new HashSet<Message>(0);

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "parentThread", orphanRemoval = true)
    @Cascade({CascadeType.REMOVE })
    private /**transient /**/ Set<Thread> subThreads = new HashSet<Thread>(0);
}

我当然对注释有很多怀疑,但这些都是相关的选择。

  • 当我删除用户时,我不想删除他的所有线程和消息,所以在@OneToMany关联上使用孤儿删除或级联删除是有意义的(即消息和线程集合)。
  • 另外,因为id是从数据库自动生成的,所以我不认为在所有实体的集合上使用注释CascadeType.UPDATE(或SAVE_UPDATE)是有意义的。
  • 线程是要管理的问题最多的实体。当我们删除一个线程时,我们希望删除它的所有子线程及其所有消息。所以,我使用CascadeType.REMOVE和孤儿删除注释。
  • 所有@ManyToOne关联,我使用CascadeType.ALL。我们的想法是,如果我们删除邮件或子线程,所有父母都将被更新。
  • 所有收藏品都不是短暂的。

当然可以随意提出建议。

不过,总的来说,这是一个问题:假设我有一个线程&#34; mThread&#34;从用户&#34; mUser&#34;开始来自不同用户的许多消息,我如何安全地删除用户? 我尝试了不同的东西,但我不确定任何事情,在大多数情况下我只有例外。


修改

我还有另一个类StorageManager<T>,用于封装实体之间的公共代码。基本上,它实现了每个事务的一个会话&#34;图案。所以每个methodX()基本上都是:

  • 调用sessionFactory.openSession()session.beginTransaction()
  • 调用session.methodX()
  • 调用transaction.commit()
  • 调用session.clear()session.close

代码示例

for (Thread t : mUser.getThreads())
    {
        t.setUser(null);
        storageManagerThread.update(t);
    }
    for (Message m : mUser.getMessages())
    {
        m.setUser(null);
        storageManagerMessage.update(t);
    }
    storageManagerUser.delete(mUser);

在此之前,数据库中的所有表都具有正确的值。但是,我不知道这是否是正确的方法,因为它留下了肮脏的收藏品。 实际上,在稍后我尝试执行其他一些选项(例如update(mThread)或从mThread删除邮件)时抛出了NullPointerException。为什么是这样?

0 个答案:

没有答案