2013-10-10 45 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

相关问题