2013-10-10 76 views
2

我有一個用戶和標籤表,並且還有一個user_tag_xref表,它包含多對多的關係.net netbeans爲我生成實體類(使用eclipselink),下面是實體映射在標籤上類User類jpa:當合並多對多以前的記錄被刪除

@ManyToMany(mappedBy = "usersList") 
    private List<Tags> tagsList; 

關係

@JoinTable(name = "USERS_TAG_XREF", joinColumns = { 
     @JoinColumn(name = "TAG_ID", referencedColumnName = "TAG_ID")}, inverseJoinColumns = { 
     @JoinColumn(name = "USER_ID", referencedColumnName = "USER_ID")}) 
    @ManyToMany 
    private List<Users> usersList; 

現在我正在我的業務邏輯問題的REST服務,JSON客戶端消耗此會見HOD

@POST 
    @Path("/registration2/tag") 
    @Consumes(MediaType.APPLICATION_JSON) 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response registration2_3(List<Tags>tagList,@Context HttpServletRequest req){ 

     Profile p =(Profile) registerMap.get(req.getSession().getId()); 
    Users u = em.find(Users.class,p.getUserId()); 


    for(Tags t : tagList){ 
     t.getUsersList().add(u); 
     u.getTagsList().add(t); 
     em.merge(t); 
     em.merge(u); 

    }  
    logger.log(Level.INFO, "the taglist created for user"); 

     return Response.ok(u,MediaType.APPLICATION_JSON).build(); 
    } 

的問題是,每次我合併新用戶創建一個多對多的關係,如果現有的用戶ID = 6201與2,3,4標籤,而新用戶嘗試使用以標記ID 2,3,4, 刪除現有用戶並且新用戶合併到標籤。我已閱讀了幾篇關於重寫散列和等於我的實體類中的方法的文章,這些方法在eclipselink中默認被覆蓋,我也無法將我的集合類型更改爲設置或集合,因爲列表<>類型對於json數組完全適用。我已經很難過了,現在已經過了24小時,它可能是默認的映射策略是錯誤的嗎?我需要cascasde嗎?

+0

任何人可以請幫助?請 –

+0

當您調用合併時,t.getUserList()中的內容是什麼? t和tagList來自哪裏?如上所述,在調用合併時,您必須小心標籤實際上反映了數據庫中的內容。如果只是部分完成,則用部分數據覆蓋整個數據。另外,什麼是刪除,它只是連接表中的引用? – Chris

+0

Chris的好問題。連接表中的引用是否被刪除? – Shailendra

回答

2

在使用合併作爲其語義時(如解釋here)與剛更新有點不同,您必須格外謹慎。 由於你的關係是雙向的,而用戶是反面的,所以所有的關係持久性將由 標籤處理。假設您標籤列表包含沾邊的標籤,這意味着所有的標籤都有自己的ID設置,那麼你需要遍歷標記列表

Tag managedTag = em.merge(t); 

這需要照顧,如果t是新的實例(非託管),那麼它的持久性陳述會返回 必須在那裏使用,或者如果實例設置了它們的id,那麼ORM將使用來自數據庫的數據創建一個託管實例(或者如果它存在那裏,則從第一/第二級緩存創建)。返回的實例是一個管理

for(Tags t : tagList){ 
     Tag managedTag = em.merge(t); 
     managedTag.getUsersList().add(u); 
     u.getTagsList().add(t);   
     User managedUser = em.merge(u); 

    } 

你也可以設置在標籤一側合併級聯選項,以節省您的第二個合併呼叫並讓ORM自動管理的關係。

+0

我試過你的代碼,它仍然給了我相同的結果,我修改了你的代碼,可能需要將託管標籤添加到u.getTagList()。add(managedTag); –

+1

將em.merge(t)替換爲em.find(Tags.class,t.getId()),看看是否可以解決問題。 – Chris

+0

whooaaaaa,我用em.find(Tags.class,tgetId())替換它,它工作,請問爲什麼它工作?不是從標籤合併managedTag = em.merge(t);實際上沒有將其合併到受管狀態? –

1

下面是合併行爲與分離的實體和關係。

@Entity 
public class Tag { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int  id; 

    private String  name; 

    @ManyToMany(cascade=CascadeType.ALL) 
    private List<User> users = new ArrayList(); 
....................... 
} 


@Entity 
public class User { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int  id; 

    private String name; 
    @ManyToMany(mappedBy="users",cascade=CascadeType.ALL) 
    private List<Tag> tags = new ArrayList(); 
........................ 
} 

TestProgram是SQL生成

EntityManagerFactory emf = Persistence.createEntityManagerFactory("Test"); 
EntityManager em = emf.createEntityManager(); 
em.getTransaction().begin(); 

User user = new User(); 
user.setName("User"); 
User managedUser = em.merge(user); 
int userId = managedUser.getId(); 
//create a tag   
Tag tag = new Tag(); 
tag.setName("Tag"); 
tag.addUser(managedUser); 
Tag managedTag = em.merge(tag); 
//save the id locally 
int savedId = managedTag.getId(); 
//managed tag was sent to UI where its name will be changed to "Changed Tag" 
em.getTransaction().commit(); 
em.close(); 

//create another transaction 
EntityManager em1 = emf.createEntityManager(); 
em1.getTransaction().begin(); 

//simulate a tag sent form UI 
Tag tagFromUI = new Tag(); 
tagFromUI.setId(savedId); 
tagFromUI.setName("Changed Tag"); 

// I want to associate a new user to this tag 
// so create a new user 
User newUser = new User();   
newUser.setName("newUser");  
tagFromUI.addUser(newUser); 
Tag managedTagFromUI = em1.merge(tagFromUI); 


em1.getTransaction().commit(); 
em1.close(); 
emf.close(); 

這裏和相應的解釋,如果你正在查看

//First transaction begins 
insert into User (name) values ('User'); 
insert into Tag (name) values ('Tag'); 
insert into Tag_User (tags_id, users_id) values (1, 1); 
//First transaction ends 
//Second transaction begins 
// Since a detached tag is merged, hibernate queries for tag id 1 to load it in persistent context 
//This tag is associated with a user 
select tag0_.id as id1_3_1_, tag0_.name as name2_3_1_, users1_.tags_id as tags_id1_3_3_, user2_.id as users_id2_4_3_, user2_.id as id1_5_0_, user2_.name as name2_5_0_ from Tag tag0_ left outer join Tag_User users1_ on tag0_.id=users1_.tags_id left outer join User user2_ on users1_.users_id=user2_.id where tag0_.id=1; 
//copies the state of detached tag from UI to the managed tag and sends update 
update Tag set name='Changed Tag' where id=1; 
//since merge is cascaded, hibernate looks for the user list of supplied tag and sees an transient User 
// the transient instance is merged (created new in database as it is not yet persisted) 
insert into User (name) values ('newUser'); 
// merge is called on this new managed instance and the resulted instance is set in the managed Tag instance automatically 
//but for this the old relation has to be broken 
delete from Tag_User where tags_id=1; 
// and the new relation has to be added in database 
insert into Tag_User (tags_id, users_id) values (1, 2); 
//second transaction ends 
+0

我的標籤類使用基本,而用戶類使用GeneratedValue,所以標籤值是固定的,我沒有問題,許多使用jsf客戶端或Java GUI客戶端,但自從我開始工作時,像一個前端人做角js和發送json對象,它完全感覺像是一個新手。令人沮喪的。我的合併/後操作不斷刪除與相關記錄 –

+0

如何實現這種行爲在春季啓動,數據休息和jpa應用程序我的問題在這裏http://stackoverflow.com/questions/43111692/unable-to-save-data -to-複合表經由彈簧數據靜止-JSON-交/ 43112334?noredirect = 1個#comment73320408_43112334 – Taimur

相關問題