我遇到了一个奇怪的问题,每当我尝试在我的应用程序中编辑寄存器而不是更新实体的状态时,它会持续存在一个新的。这是我的update
方法
public void update(Object obj) {
EntityManagerFactory fac = Persistence.createEntityManagerFactory("crud");
EntityManager em = fac.createEntityManager();
em.merge(obj);
em.getTransaction().begin();
em.getTransaction().commit();
em.close();
fac.close();
}
我的猜测是当我提交编辑表单并且调用setter时Id
以某种方式设置为0.这可能发生吗?表格如下:
<h:form>
<p:panelGrid columns="2" style="margin: 0 auto;">
<f:facet name="header">
Edit form
</f:facet>
Name:
<h:inputText id="nome" value="#{editUserBean.userToEdit.name}"/>
Age:
<h:inputText value="#{editUserBean.userToEdit.age}" converter="javax.faces.Integer"/>
Pass:
<h:inputText value="#{editUserBean.userToEdit.password}"/>
Gender:
<h:selectOneRadio value="#{editUserBean.userToEdit.gender}" style="font-size: 12px;">
<f:selectItem itemValue="Masc" itemLabel="Masc" />
<f:selectItem itemValue="Fem" itemLabel="Fem" />
</h:selectOneRadio>
<f:facet name="footer">
<div align="center">
<h:commandButton value="save" actionListener="#{editUserBean.save}" icon="ui-icon-check"/>
</div>
</f:facet>
</p:panelGrid>
</h:form>
Hibernate
正在查询:
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
insert
into
users
(age, gender, name, password, id)
values
(?, ?, ?, ?, ?)
答案 0 :(得分:1)
我不知道你是否已经尝试了这个但是检查了hibernate配置文件...然后可能是包含值create的标签之一。将其更改为更新。希望这有帮助
答案 1 :(得分:1)
一些事情......首先将这样的PersistenceContext注入您的EJB:
@PersistenceContext
private EntityManager em;
接下来,使用正确的自动事务处理标记您的函数或整个EJB:
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class MyServiceEJBThingy {
@PersistenceContext
private EntityManager em;
在您的方法中,除了您的业务逻辑之外,不要做任何事情。交易信息现在可以自动处理:
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class MyServiceEJBThingy {
@PersistenceContext
private EntityManager em;
public void update(Object obj) {
//GUI independent business logic here
em.merge(obj);
}
}
最后,现在将您的EJB注入视图控制器中(假设您正在使用MVVM模式):
@RequestScoped (or something)
public class EditUserBean {
@Inject
private MyServiceEJBThingy myServiceEJBThingy;
public void update(Object obj) {
// GUI logic here
myServiceEJBThingy.update(obj);
}
}
更简单的是吗? :) Java可以非常简单和高效。我不确定你正在使用什么容器,但我建议使用Apache TomEE。查看他们庞大的最新示例库here。祝你好运!!!
答案 2 :(得分:1)
实际问题出在JSF层。
所有证据都指出editUserBean
请求作用域。这意味着每个请求都会获得一个新bean。
因此,我们正在为每个请求使用新 userToEdit
bean。它的属性可以是null
或基元的默认值(例如0
int
和long
),除非你明确声明了属性内的属性的默认值。豆。这包括id
,在您的情况下为0
。
合并bean时,持久化上下文中没有标识为0
的实体或数据库中的相应条目,因此merge
将保留新实体。如果要为主键生成值,则可能永远不会将0
作为id
,因此JPA层将保持新实体的持久性。
针对此问题的一个简单修复方法是将用户信息存储在具有broader scope的bean中,例如会话范围或用户定义的会话范围:< / p>
@ConversationScoped
class UserToEdit extends User {
// ... or if you want, create a HAVE-A relationship
}
然后你可以照常注入你的bean,并且存储的id
将在请求之间存活(不要忘记清理;正确划分对话边界和/或清理会话bean)。
另一种解决方法 - 如果您绝对必须将用户信息保留在请求范围中 - 使用隐藏字段来保存id
的值(以及任何不可编辑的值)你希望的财产)。这样,用户id
也将在下一个请求时提交,模型将正确更新。
<h:inputHidden value="#{editUserBean.userToEdit.id}" />
警告:虽然此解决方法非常受欢迎,但只有在当前用户能够更新任何其他用户的信息时才能执行此操作。为什么?恶意用户可以轻松操纵DOM,以便更改user.id
和/或提交包含任何id
的虚假请求以滥用系统。