所以我有一个基本的JSF Datatable,相关部分是:
<h:dataTable value="#{actorTableBackingBean.allActors}" var="actor">
<h:column headerText="Actor Name" sortBy="#{actor.firstName}">
<h:outputText value="#{actor.firstName}" />
</h:column>
<h:column>
<h:form>
<h:commandButton value="Delete Actor"
action="#{actorTableBackingBean.deleteActor(actor)}"/>
</h:form>
</h:column>
<h:column>
<h:form>
<h:commandButton value="Randomize Actor Name"
action="#{actorTableBackingBean.editActor(actor)}"/>
</h:form>
</h:column>
</h:dataTable>
这就是ActorTableBackingBean的样子:
@Named
@RequestScoped
public class ActorTableBackingBean implements Serializable {
@Inject
ActorDao actorDao;
private List<Actor> allActors;
public List<Actor> getAllActors() {
return allActors;
}
@PostConstruct
public void fillUp(){
allActors = actorDao.getAllT();
}
public String deleteActor(Actor a){
removeActor(a);
return "/allActors.xhtml";
}
private String removeActor(Actor a){
try{
actorDao.deleteActor(a);
return null;
}catch (Exception e){
return null;
}
}
public String editActor(Actor actor){
actor.setFirstName("SomeRandonName");
actorDao.editActor(actor);
return "/allActors.xhtml";
}
}
最后是演员道:
@Stateless
public class ActorDao extends GeneralDao<Actor> implements Serializable {
@Override
protected Class<Actor> getClassType() {
return Actor.class;
}
@Override
public Actor getWithId(int id){
TypedQuery<Actor> typedQuery =
em.createQuery("Select a From Actor a WHERE a.actorId =" + id,Actor.class);
return typedQuery.getSingleResult();
}
public void editActor(Actor a){
em.merge(a);
}
public void deleteActor(Actor a){
em.remove(a);
}
}
因此,您可以看到编辑Actor调用 em.merge(a),这样就可以了。 但是 em.remove(a)将返回:
Caused by: java.lang.IllegalArgumentException: Entity must be managed to call remove: com.tugay.sakkillaa.model.Actor@6ae667f, try merging the detached and try the remove again.
即使我尝试:
public void deleteActor(Actor a){
em.merge(a);
em.remove(a);
}
我仍然得到同样的例外。
那么如何编辑行,而不是删除它?
我唯一能让它发挥作用的方式是:
public void deleteActor(Actor a){
Actor actorToBeRemoved = getWithId(a.getActorId());
em.remove(actorToBeRemoved);
}
我做错了什么,或者无法理解?
答案 0 :(得分:40)
merge()方法执行以下操作:它接受一个分离的实体,从数据库加载具有相同ID的附加实体,将分离的实体的状态复制到附加的实体,并返回附加的实体。正如您在本说明中所述,分离的实体根本不会被修改,也不会附加。这就是你得到例外的原因。
如果你这样做,你就不会得到它
public void deleteActor(Actor a){
a = em.merge(a); // merge and assign a to the attached entity
em.remove(a); // remove the attached entity
}
也就是说,合并是完全没必要的,因为您要做的就是删除实体。最后一个解决方案很好,除了它真正从数据库加载实体,这也是不必要的。你应该简单地做
public void deleteActor(Actor a){
Actor actorToBeRemoved = em.getReference(Actor.class, a.getActorId());
em.remove(actorToBeRemoved);
}
请注意,您的getWithId()
方法效率不高,而且不必要复杂。你应该用
public Actor getWithId(int id){
return em.find(Actor.class, id);
}
将使用第一级缓存(也可能是第二级缓存)以避免不必要的查询。