2012-12-02 23 views
1

具有不同的行爲啊,我知道,標題是有點混亂,但這裏的情況是:JPA在一個項目中插入觸發前執行,並在另一個

我有兩個項目,即應工作方式相同。他們都訪問Oracle數據庫。 Oracle數據庫上的每個表都有一個TABLENAME_ID列,它是主鍵,它與BEFORE INSERT觸發器相關聯,該觸發器執行TABLENAME_SEQ nextval()以插入到TABLENAME_ID列中。 (瞭解?)。在這種環境下,通過SQL插入工作正常。

這就是說讓我們去的問題:

我有一個使用其中從數據庫表生成實體JPA一個PROJECT1。在這個項目上生成的實體工作正常,完成CRUD和搜索。實體與SequenceGenerator註釋相關聯,DOES不會在插入時執行數據庫觸發器,因此無論使用何種通道(系統或SQL DML語句),都會順序生成id行。

現在我必須創建第二個項目,該項目的行爲方式應該是相同的,但不是。在這個項目上,當我創建一個實體時,它會檢索我。即ID = 3,但實際上在數據庫上寫入ID = 4。所以,如果我得到這個相同的實體並嘗試對它進行更新,JPA會嘗試再次插入它,並給我一個錯誤。

任何線索?一些代碼如下波紋管:

實體實例(從Project 1):

@Entity 
public class Category implements Serializable { 

    private static final long    serialVersionUID = 1L; 

    @Id 
    @SequenceGenerator(name = "CATEGORY_CATEGORYID_GENERATOR", sequenceName = "CATEGORY_SEQ", allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CATEGORY_CATEGORYID_GENERATOR") 
    @Column(name = "CATEGORY_ID", unique = true, nullable = false, precision = 10) 
    private long       categoryId; 

    @Column(name = "IS_ACTIVE", nullable = false, precision = 3) 
    private boolean       isActive; 

    @Column(name = "LONG_TITLE", nullable = false, length = 250) 
    private String       longTitle; 

    public Category() { 
    } 

    public long getCategoryId() { 
     return this.categoryId; 
    } 

    public boolean getIsActive() { 
     return this.isActive; 
    } 

    public String getLongTitle() { 
     return this.longTitle; 
    } 

    public void setCategoryId(long categoryId) { 
     this.categoryId = categoryId; 
    } 

    public void setIsActive(boolean isActive) { 
     this.isActive = isActive; 
    } 

    public void setLongTitle(String longTitle) { 
     this.longTitle = longTitle; 
    } 

} 

實體實例(從Project 2):

@Entity 
public class Author implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @SequenceGenerator(name = "AUTHOR_AUTHORID_GENERATOR", sequenceName = "AUTHOR_AUTHOR_ID_SEQ", allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AUTHOR_AUTHORID_GENERATOR") 
    @Column(name = "AUTHOR_ID", unique = true, nullable = false, precision = 10) 
    private long    authorId; 

    @Column(name = "ADDRESS_COMPLEMENT") 
    private String    addressComplement; 

    @Column(name = "AUTHOR_KIND") 
    private int     authorKind; 

    @Column(name = "BUILDING_NUMBER") 
    private String    buildingNumber; 

    private String    city; 

    // bi-directional many-to-one association to Product 
    @OneToMany(mappedBy = "author") 
    private List<Product>  products; 

    public Author() { 
    } 

    public String getAddressComplement() { 
     return addressComplement; 
    } 

    public long getAuthorId() { 
     return authorId; 
    } 

    public int getAuthorKind() { 
     return authorKind; 
    } 

    public String getBuildingNumber() { 
     return buildingNumber; 
    } 

    public String getCity() { 
     return city; 
    } 

    public List<Product> getProducts() { 
     return products; 
    } 

    public void setAddressComplement(String addressComplement) { 
     this.addressComplement = addressComplement; 
    } 

    public void setAuthorId(long authorId) { 
     this.authorId = authorId; 
    } 

    public void setAuthorKind(int authorKind) { 
     this.authorKind = authorKind; 
    } 

    public void setBuildingNumber(String buildingNumber) { 
     this.buildingNumber = buildingNumber; 
    } 

    public void setCity(String city) { 
     this.city = city; 
    } 

    public void setProducts(List<Product> products) { 
     this.products = products; 
    } 

} 

EDIT

如JScoobyCed問這裏遵循如何使用第二實體代碼:

// ... 
Author author = new Author(); 
// Here follows setters 
// Code below returns, ie, author_id = 3, but saves author_id = 4 on database 
author = authotEjb.create(author); 
// ... 
product.setAuthor(author); 
// Don't find author_id = 3 on database and tries to insert author again 
// or complains about PERSIST cascade on Product entitiy. 
product = productEjb.update(product) 

EJB在create()方法上使用EntityManager.persist(),在update方法上使用EntityManager.merge()。

編輯2

添加的順序和觸發碼。每個表都有它自己的序列和它自己的觸發遵循相同的模式TABLENAME_SEQ和TABLENAME_TRG:

序列碼:

CREATE SEQUENCE AUTHOR_SEQ MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 NOCACHE ORDER NOCYCLE; 

觸發代碼:

create or replace 
trigger author_trg before insert on author 
for each row 
begin 
    select author_seq.nextval into :new.author_id from dual; 
end; 
+0

你能發表關於你如何使用這些實體的代碼,特別是你的第二個項目。也許你的實體沒有(不再)由JPA在你想更新的時候管理。 – JScoobyCed

+0

嗨JScoobyCed,編輯。 –

+0

兩個表上的觸發器是否相同?如果在設置之前已經設置了id,是否觸發類別檢查? – Nemanja

回答

0

無論你的觸發和JPA會嘗試分配序列號,所以這不適用於任何一個系統。

如果插入提供了id(只有在爲null的情況下才需要),則需要修復觸發器以不分配id。

否則,您需要某種方法從IDA的觸發器中獲取ID。如果使用EclipseLink,則可以使用@ReturnInsert註釋,但通常修復觸發器會更好。

+0

奇怪的是,正如前面所說,我有兩個項目,這個場景(插入前調用序列的觸發器)在Project 1上工作,但在Project 2上不工作。 –

0

我們決定禁用數據庫觸發器...

我們懷疑在類似的情景項目1部作品,因爲Ø遠程EJB,但我們不能完全肯定。感謝所有在這個問題上試圖幫助我的人。

相關問題