簡體   English   中英

enitityManager.find和entityManager.createQuery有什么區別?

[英]What is the difference between enitityManager.find and entityManager.createQuery?

好吧,我正在使用帶有hibernate的EJB 3.0,我們將.ear文件放入嵌入Apache Tomcat 6.0.18的Easy-Beans 1.0.1(帶有Hibernate)部署目錄中。 所以我的數據庫必須堅持這樣的事情:

@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來檢索和刪除多個實體,它工作順利。 那為什么現在不行呢?

更新:調用Query q=...然后刪除BookAuthors將BookAuthorsBooks刪除,而不是從Authors刪除。 在第二種情況下,它從兩組中刪除。 當使用baQuery.equals(baFind)進行比較時,兩個ba都具有相同的散列並返回true

任何澄清為什么兩個函數將返回相同的對象,但調用remove將根據是否調用query / find不同的行為?

也許這與BookAuthor缺少equals() / hashCode() BookAuthor 如果是這樣,在查詢的情況下,您有幾個具有相同狀態的BookAuthor不同實例,因此不會從AuthorBook的相應集中刪除它們。

據我所知, Query.getSingleResult()在某些情況下刷新會話,我不確定EntityManager.find() 我會遵循axtavt的建議並仔細檢查你的實體是否正確地從集合中刪除。 我也會在em.remove(ba);之前將此聲明em.remove(ba); 確保您的ba對象重新附加到會話:

ba = em.merge(ba);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM