为什么Hibernate 4.3.7.Final saveOrUpdate会在每次插入后触发更新?

时间:2015-03-05 07:00:43

标签: spring-4 hibernate-4.x

在早期版本的Hibernate中,saveorUpdate会根据实体触发插入或更新查询。

但是在hibernate 4.3.7每次插入后都会触发更新查询。我看到插入和更新查询。

域对象

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="LOGGER")
public class MessageLogger extends BaseDomainObject implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Column(name = "CP")
    private String cpId;

    @Column(name = "ACTION")
    private String action;

    @Column(name = "REQUEST", columnDefinition="text" )
    private String request;

    @Column(name = "RESPONSE", columnDefinition="text" )
    private String response;

    @Column(name = "SEND_FROM")
    private String sendFrom;

    @Column(name = "SEND_TO")
    private String sendTo;

    public MessageLogger(){

    }

    public MessageLogger(String cpId,String action,String sendFrom,String sendTo,String request){
        this.cpId = cpId;
        this.action=action;
        this.sendFrom=sendFrom;
        this.sendTo=sendTo;
        this.request=request;
    }


    public String getRequest() {
        return request;
    }

    public void setRequest(String request) {
        this.request = request;
    }

    public String getResponse() {
        return response;
    }

    public String getSendFrom() {
        return sendFrom;
    }

    public void setSendFrom(String sendFrom) {
        this.sendFrom = sendFrom;
    }

    public String getSendTo() {
        return sendTo;
    }

    public void setSendTo(String sendTo) {
        this.sendTo = sendTo;
    }

    public void setResponse(String response) {
        this.response = response;
    }

    public String getCpId() {
        return cpId;
    }

    public void setCpId(String cpId) {
        this.cpId = cpId;
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }

}

基础域对象

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;

@MappedSuperclass
public abstract class BaseDomainObject implements LastModifiable,Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @Version
    @Column(name = "VERSION", columnDefinition = "int default 0")
    private int version;

    @Column(name = "CREATION_TIMESTAMP", nullable = false, insertable = false, updatable = false, columnDefinition = "timestamp default CURRENT_TIMESTAMP")
    @Temporal(TemporalType.TIMESTAMP)
    private Date creationTimestamp;

    @Column(name = "LAST_UPDATED_TIMESTAMP", columnDefinition = "datetime")
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdatedTimestamp;

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public Date getCreationTimestamp() {
        return creationTimestamp;
    }

    public void setCreationTimestamp(Date creationTimestamp) {
        this.creationTimestamp = creationTimestamp;
    }

    public Date getLastUpdatedTimestamp() {
        return lastUpdatedTimestamp;
    }

    public void setLastUpdatedTimestamp(Date lastUpdatedTimestamp) {
        this.lastUpdatedTimestamp = lastUpdatedTimestamp;
    }

    public Long getId() {
        return id;
    }

}

DAO Layer

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public class MessageLoggerDAOImpl 
        implements MessageLoggerDAO {

    @Autowired
    SessionFactory sessionFactory;

    @Override
    @Transactional
    public MessageLogger createOrUpdate(MessageLogger messageLogger) {
        Session s = sessionFactory.getCurrentSession();
        s.saveOrUpdate(messageLogger);
        return  messageLogger;
    }
}

Spring应用程序上下文配置: - 配置hibernate会话工厂

<tx:annotation-driven />

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${database.driver}" />
        <property name="url" value="${database.url}" />
        <property name="username" value="${database.user}" />
        <property name="password" value="${database.password}" />
    </bean>

    <bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.my.server.domainobjects" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
        </props>
    </property>
</bean>

        <bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>

Log4j日志: - 当我第一次运行MessageLoggerDAOmpl的createOrUpdate方法插入MessageLogger实体时,我看到下面的两个查询

[05 Mar 2015 12:11:15:365] DEBUG SQL::logStatement:109 - insert into LOGGER (LAST_UPDATED_TIMESTAMP, VERSION, ACTION, CP, REQUEST, RESPONSE, SEND_FROM, SEND_TO) values (?, ?, ?, ?, ?, ?, ?, ?)

[05 Mar 2015 12:11:15:546] DEBUG SQL::logStatement:109 - update LOGGER set LAST_UPDATED_TIMESTAMP=?, VERSION=?, ACTION=?, CP=?, REQUEST=?, RESPONSE=?, SEND_FROM=?, SEND_TO=? where ID=? and VERSION=?

1 个答案:

答案 0 :(得分:0)

它不是bug。我的错误。我在saveorUpdate上也有事件监听器,我也在其中保存对象。

@Component
public class SaveOrUpdateDateListener extends DefaultSaveOrUpdateEventListener {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Override
    public void onSaveOrUpdate(SaveOrUpdateEvent event) {
        if (event.getObject() instanceof LastModifiable) {
            LastModifiable record = (LastModifiable) event.getObject();
            record.setLastUpdatedTimestamp(new Date());
        }
        //super.onSaveOrUpdate(event); // remove this line solve my problem
    }
} 

很抱歉给您带来不便