Java JPA/Hibernate不使用任何命令在表中执行更新
好的,我使用JSF+Hibernate/JPA,我有以下代码:Java JPA/Hibernate不使用任何命令在表中执行更新,java,hibernate,jsf,jpa,Java,Hibernate,Jsf,Jpa,好的,我使用JSF+Hibernate/JPA,我有以下代码: public void loadAddressByZipCode(ActionEvent event){ Address address = boDefault.findByNamedQuery(Address.FindByZipCode, 'zipCode', bean.getAddress().getZipCode()); if (address == null){ //This zip cod
public void loadAddressByZipCode(ActionEvent event){
Address address = boDefault.findByNamedQuery(Address.FindByZipCode, 'zipCode', bean.getAddress().getZipCode());
if (address == null){
//This zip code not exists in db
}else{
bean.setAddress(address);
}
}
在XHTML页面的inputText组件中的每个onBlur中都会调用上述方法,该inputText的属性值如下:{addressMB.bean.address.zipCode}
所以,当用户在XHTML页面中键入一个新的邮政编码时,这个值在bean.getAddress.setZipCode中设置,我在数据库中搜索这个值。但是调试我的应用程序时,我发现当我执行bean.getAddress.getZipCode时,Hibernate会启动一个更新地址集。。。在我的数据库里。我如何防止这种情况发生,以及为什么会发生这种情况
编辑1:
这是我真正实现的方法
public void carregarLogradouroByCep(AjaxBehaviorEvent event) {
List listReturn = getBoPadrao().findByNamedQuery(
Logradouro.FIND_BY_CEP,
new NamedParams("cep", bean.getLogradouro().getCep()));
if (listReturn.size() > 0) {
Logradouro logradouro = (Logradouro) listReturn.get(0);
bean.setLogradouro(logradouro);
}else{
bean.setLogradouro(new Logradouro());
}
}
这是我的onblur事件组件:
<p:inputText value="#{enderecoMB.bean.logradouro.cep}" id="cep"
required="true" requiredMessage="O CEP é obrigatório">
<p:ajax event="blur"
listener="#{enderecoMB.carregarLogradouroByCep}"
update=":formManterEndereco:logradouro, :formManterEndereco:cidade, :formManterEndereco:estado,
:formManterEndereco:bairro" />
</p:inputText>
但更新会自动继续
编辑2:My FIND_BY_CEP查询
"SELECT c FROM Endereco c JOIN FETCH c.tipoEndereco JOIN FETCH c.logradouro"
编辑3:我的实体
Endereco.java
@Entity
@NamedQueries(value = { @NamedQuery(name = "Endereco.findAllCompleto", query = "SELECT c FROM Endereco c "
+ "JOIN FETCH c.tipoEndereco " + "JOIN FETCH c.logradouro") })
@Table(name = "endereco")
public class Endereco extends AbstractBean {
/**
*
*/
private static final long serialVersionUID = 5239354646908722819L;
public Endereco(){
logradouro = new Logradouro();
}
@Transient
public static final String FIND_ALL_COMPLETO = "Endereco.findAllCompleto";
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_tipo_endereco")
private TipoEndereco tipoEndereco;
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST,CascadeType.MERGE})
@JoinColumn(name = "id_logradouro")
private Logradouro logradouro;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_pessoa")
private Pessoa pessoa;
@Column
private String numero;
@Column
private String complemento;
public Logradouro getLogradouro() {
return logradouro;
}
public void setLogradouro(Logradouro logradouro) {
this.logradouro = logradouro;
}
public TipoEndereco getTipoEndereco() {
return tipoEndereco;
}
public void setTipoEndereco(TipoEndereco tipoEndereco) {
this.tipoEndereco = tipoEndereco;
}
public String getNumero() {
return numero;
}
public void setNumero(String numero) {
this.numero = numero;
}
public String getComplemento() {
return complemento;
}
public void setComplemento(String complemento) {
this.complemento = complemento;
}
public Pessoa getPessoa() {
return pessoa;
}
public void setPessoa(Pessoa pessoa) {
this.pessoa = pessoa;
}
}
Logradouro.java
@Entity
@NamedQueries(value = { @NamedQuery(name = "Logradouro.findByCep", query = "SELECT c FROM Logradouro c "
+ "JOIN FETCH c.bairro "
+ "JOIN FETCH c.cidade "
+ "WHERE c.cep = :cep "
+ "ORDER BY c.logradouro") })
@Table(name = "logradouro")
public class Logradouro extends AbstractBean {
public Logradouro(){
this.cidade = new Cidade();
this.bairro = new Bairro();
}
/**
*
*/
private static final long serialVersionUID = 1L;
@Transient
public static final String FIND_BY_CEP = "Logradouro.findByCep";
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST,CascadeType.MERGE})
@JoinColumn(name = "id_cidade")
private Cidade cidade;
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST,CascadeType.MERGE})
@JoinColumn(name = "id_bairro")
private Bairro bairro;
@Column
private String cep;
@Column
private String logradouro;
public Cidade getCidade() {
return cidade;
}
public void setCidade(Cidade cidade) {
this.cidade = cidade;
}
public Bairro getBairro() {
return bairro;
}
public void setBairro(Bairro bairro) {
this.bairro = bairro;
}
public String getCep() {
return cep;
}
public void setCep(String cep) {
this.cep = cep;
}
public String getLogradouro() {
return logradouro;
}
public void setLogradouro(String logradouro) {
this.logradouro = logradouro;
}
}
默认情况下,Hibernate使用entitymanager自动处理实体。您的bean就是这样一个实体,因此每当entitymanager觉得是时候刷新数据库时,它就会这样做。如果要手动刷新,则需要查看以下构造:
entityManager.setFlushMode(javax.persistence.FlushModeType.MANUAL);
我认为你误用了冬眠。ORM的主要思想是允许您编写代码,忽略某些东西进入数据库这一事实。您的域模型必须在没有任何数据库的情况下完全可测试。ORM不是关系数据库管理的抽象,它是对象模型的抽象。如果您需要显式地执行插入和更新,那么最好使用一些活动记录实现,或者查看像MyBatis这样的轻量级映射器
为什么要阻止数据库更新?财产变了,对吗?所以,让Hibernate来决定是否以及何时必须将其新值写入数据库。我认为这不是一个好主意,让Hibernate自动执行提交,至少对于我的业务规则来说是这样。我将尝试此FlushModeType.COMMIT并返回此处。我尝试过使用更多信息编辑我的帖子,但更新仍在继续,但现在更新发生在SELECT语句之后。@Makky,我发布了所有必要的代码显示命名查询FIND_BY_cep还检查您的表中是否有触发器。我没有任何触发器。否。当我生成bean.getLogradouro.getcep时,会触发DB更新。问题是:在JSF中,我用一个名为Logradouro的bean映射了所有组件,该bean由邮政编码找到。当用户键入另一个邮政编码时,必须替换此对象LOGRADOURO且不进行更新。当我在查询对象中设置getResultList时,会进行更新。我怀疑直接将域实体绑定到表单是否是一种好的做法。每次用户按下“Sumbit”或“Save”按钮时,最好映射到DTO并将数据从DTO复制到实体。也许这样改变你的方法可以解决这个问题。
entityManager.setFlushMode(javax.persistence.FlushModeType.MANUAL);