java-enitityManager.find和entityManager.createQuery有什么区别?
作者:互联网
好的,我将EJB 3.0与hibernate一起使用,我们将.ear文件放入了嵌入Apache Tomcat 6.0.18中的Easy-Beans 1.0.1(带有Hibernate)deploy目录中.
所以我的数据库必须坚持这样的事情:
@Entity
@Table(name="AUTHOR")
public class Author implements Serializable {
//////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "A_ID", unique=true, nullable = false)
private Integer id;
@Column (name = "A_NAME", unique = false, nullable = false)
private String name;
@Column (name = "A_LASTNAME", unique = false, nullable = false)
private String lastname;
@OneToMany(cascade = {ALL}, fetch = EAGER, mappedBy = "author")
private Set<BookAuthor> bookAuthors = new HashSet<BookAuthor>();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Author author = (Author) o;
if (id != null ? !id.equals(author.id) : author.id != null) return false;
return true;
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
@Entity
@Table(name = "BOOK" )
public class Book implements Serializable {
//////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////
@Id
@GeneratedValue (strategy = IDENTITY)
@Column(name = "B_ID", unique = true, nullable = false)
private Integer bid;
@Column(name = "B_YEAR", unique = false, nullable = true)
private Integer year;
@Column(name = "B_ISBN", unique = false, nullable = false)
private String isbn;
@Column(name = "B_TITLE", unique = false, nullable = false)
private String title;
@OneToMany(cascade = {ALL}, fetch = EAGER, mappedBy = "book")
private Set<BookAuthor> bookAuthors = new HashSet<BookAuthor>();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
if (isbn != null ? !isbn.equals(book.isbn) : book.isbn != null) return false;
if (bid != null ? !kid.equals(book.bid) : book.bid != null) return false;
return true;
}
@Override
public int hashCode() {
int result = bid != null ? bid.hashCode() : 0;
result = 31 * result + (isbn != null ? isbn.hashCode() : 0);
return result;
}
}
@Entity
@Table(name = "BOOK_AUTHOR")
public class BookAuthor implements Serializable {
//////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "BA_ID", unique=true, nullable = false)
private Integer id;
@Column(name = "BA_ROLE", unique = false, nullable = true)
private String role;
@ManyToOne
@JoinColumn (name = "A_ID", referencedColumnName = "A_ID", nullable = false)
private Author author;
@ManyToOne
@JoinColumn (name = "B_ID", referencedColumnName = "B_ID", nullable = false)
private Book book;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BookAuthor that = (BookAuthor) o;
if (auhtor != null ? !author.equals(that.author) : that.author != null) return false;
if (book != null ? !book.equals(that.book) : that.book!= null) return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (author != null ? author.hashCode() : 0);
result = 31 * result + (book != null ? book.hashCode() : 0);
return result;
}
}
因此,在删除项目时,我有一个实体bean,它像这样:
@Stateless
@Local(DeleteBookAuthor.class)
public class DeleteBookAuthorBean implements DeleteBookAuthor
{
@PersistenceContext(unitName="Library")
protected EntityManager em;
@Override
public void removeById(Integer id) {
try{
Query q = em.createQuery("SELECT ba FROM BookAuthor ba WHERE id = ?1");
q.setParameter(1,id);
BookAuthor ba = (BookAuthor) q.getSingleResult();
ba.getAuthor().getBookAuthors().remove(ba);
ba.getBook().getBookAuthors().remove(ba);
em.remove(ba);
}catch (Exception e){
e.printStackTrace();
}
}
}
不幸的是,当我的Servlet调用此bean时,它返回一个“已删除的实体传递给持久化”异常.但是更改行:
Query q = em.createQuery("SELECT ba FROM BookAuthor ba WHERE id = ?1");
q.setParameter(1,id);
BookAuthor ba = (BookAuthor) q.getSingleResult();
至
BookAuthor ba = em.find(BookAuthor.class, id)
使问题消失.我问的问题是为什么?在类似的情况下,我使用em.createQuery来检索和删除多个实体,并且工作顺利.那为什么现在不起作用呢?
更新:调用
查询q = …,然后删除BookAuthors,将从书中删除BookAuthor,但从作者中删除.在第二种情况下,将其从两个集合中删除.两个ba都具有相同的哈希值,并且使用baQuery.equals(baFind)进行比较时返回true.
有任何澄清为什么两个函数将返回相同的对象但调用remove的行为会有所不同,具体取决于是否调用了查询/查找?
解决方法:
可能与BookAuthor中缺少equals()/ hashCode()有关.如果是这样,则在查询的情况下,您有几个具有相同状态的BookAuthor实例,因此它们不会从Author和Book中的相应集中删除.
标签:hibernate,persistence,ejb-3-0,tomcat,java 来源: https://codeday.me/bug/20191105/1996511.html