简体   繁体   English

JPA / Hibernate在没有任何命令的情况下在表中进行更新

[英]JPA/Hibernate doing update in table without any command

Well, I work with JSF + Hibernate/JPA, I have the following code: 好吧,我使用JSF + Hibernate / JPA,我有以下代码:

  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);
   }
  }

This method above is called in every "onBlur" in inputText component in XHTML page, this inputText have the property value like this: "#{addressMB.bean.address.zipCode}" 上面的方法在XHTML页面的inputText组件中的每个“ onBlur”中都被调用,该inputText具有如下属性值:“#{addressMB.bean.address.zipCode}”

So, when user (in XHTML page) type a new Zip Code this value is setted in "bean.getAddress().setZipCode()" and i search for this value in Database. 因此,当用户(在XHTML页面中)键入新的邮政编码时,将在“ bean.getAddress()。setZipCode()”中设置此值,然后在数据库中搜索该值。 But debugging my application i discovered that when i do "bean.getAddress().getZipCode()" the Hibernate launch a "update address set ..." in my DataBase. 但是调试我的应用程序后,我发现当我执行“ bean.getAddress()。getZipCode()”时,Hibernate在我的数据库中启动了一个“更新地址集...”。 How can i prevent this and why this happens ? 我该如何防止这种情况发生,为什么呢?

EDIT 1: This is my real method implemented 编辑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());
        }
    }

This is my component with onblur event: 这是我的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>

I have a "BasicDAOImpl" that make all operations in database, so tried do it in my entityManager: 我有一个“ BasicDAOImpl”,可以在数据库中进行所有操作,因此尝试在我的entityManager中执行此操作:

@PostConstruct
    private void init(){        
        entityManager.setFlushMode(FlushModeType.COMMIT);
    }

But "update automatically" continue. 但是“自动更新”继续。

EDIT 2: My FIND_BY_CEP query 编辑2:我的FIND_BY_CEP查询

"SELECT c FROM Endereco c JOIN FETCH c.tipoEndereco JOIN FETCH c.logradouro"

EDit 3: My Entities EDit 3:我的实体

Endereco.java 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 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 uses an entitymanager to do automatic handling of your entities by default. 默认情况下,Hibernate使用entitymanager来自动处理您的实体。 Your bean is one such entity so whenever the entitymanager feels it's time to flush to the database it does so. 您的bean就是这样的一个实体,因此只要实体管理器感觉到需要刷新数据库的时候,它就会这样做。 If you want to flush manually, you'll want to have a look at such a construction: 如果要手动冲洗,则需要查看这种构造:

entityManager.setFlushMode(javax.persistence.FlushModeType.MANUAL);

I think that you misuse Hibernate. 我认为您滥用了Hibernate。 The main idea of ORM that is allows you to write code, ignoring that fact, that something goes into database. ORM的主要思想是允许您编写代码,而忽略了将某些内容存入数据库的事实。 Your domain model must be completetly testable without any database. 您的域模型必须完全可测试,没有任何数据库。 ORM is not abstraction to manage with relation database, it is abstraction for your object model. ORM不是用关系数据库管理的抽象,而是您的对象模型的抽象。 If you need to explicitly do insert s and updates , you better use some active record implementation or look at lightweight mapper like MyBatis . 如果需要显式地执行insertupdates ,则最好使用一些活动记录实现或查看MyBatis类的轻量级映射器。

And why you want to prevent database update? 以及为什么要阻止数据库更新? Property is changed, right? 财产变了吧? So let Hibernate decide, whether and when its new value must be written to database. 因此,让Hibernate决定是否以及何时将其新值写入数据库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM