Spring JPA / Hibernate在使用@Modifying和@Query

时间:2018-04-26 21:29:14

标签: java spring spring-data spring-data-jpa

我有一个商业类的弹簧库:

public interface BusinessRepository extends JpaRepository<Business, String> {

这包括一个只更新一个字段的简单方法(updateDatetime):

@Modifying
@Query("update Business business set business.updateDatetime = :updateDatetime where business.businessKey = :businessKey")
int setUpdateDatetimeForBusiness(@Param("updateDatetime") String updateDatetime, @Param("businessKey") String businessKey);

问题在于我称这种方法:

businessRepository.setUpdateDatetimeForBusiness(business.getUpdateDatetime(), business.getBusinessKey());

日志显示以下内容:

Hibernate: update business set name=?, timezone=?, updatedatetime=? where business_id=?
Hibernate: update business set updatedatetime=? where business_id=?

该方法调用实体的完整更新,然后调用我的更新。我应该更改什么来调用第二次更新?

1 个答案:

答案 0 :(得分:-1)

@Query(value="update something", nativeQuery=true)

nativeQuery=true尝试添加此

更新

很抱歉没有仔细阅读这个问题。

由于你提供的炎症,我无法找到问题所在。但我确实有  给你的建议。

EntityManager管理的实体可以自动持久存储到数据库中,而您记录Hibernate: update business set name=?, timezone=?, updatedatetime=? where business_id=?似乎更新了所有字段?如果是这样,更新更有可能由EntityManager调用。

您可以将flushMode更改为COMMIT,看看是否会发生变化。 (仅用于测试问题是否由EntityManager自动更新引起)
  例如:弹簧靴中的spring.jpa.properties.org.hibernate.flushMode=COMMIT

我的测试代码:

服务:

import cn.eeemt.dao.TagRepository;
import cn.eeemt.entity.Tag;
import cn.eeemt.service.TagService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Optional;

@Service
public class TagServiceImpl implements TagService {

    @Resource
    private TagRepository tagRepository;

    @Override
    public void update(String newDescription) {
        Tag tag = step1(newDescription);
        step2(tag.getDescription(), tag.getId());
    }

    @Transactional
    public Tag step1(String newDescription) {
        Optional<Tag> byId = tagRepository.findById(1);
        Tag tag = byId.orElseThrow(RuntimeException::new);
        System.out.println(tag);
        tag.setDescription(newDescription);
        // tagRepository.save(byId.get());  // I did not update it!!!
        return tag;
    }

    private void step2(String description, Integer id) {
        tagRepository.updateSome(description, id);
    }
}  

存储库:

import cn.eeemt.entity.Tag;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

public interface TagRepository extends JpaRepository<Tag, Integer> {

    @Modifying
    @Transactional
    @Query("update Tag tag set tag.description = :description where tag.id = :id")
    void updateSome(@Param("description") String description, @Param("id") int id);
}

spring.jpa.properties.org.hibernate.flushMode=ALWAYS

日志看起来像:

  

标记{id = 1,name =&#39; ffadsfasd&#39;,description =&#39; dasfadsg&#39;,articles = []}
  Hibernate:更新标签集description = ?, name =?其中id =?
  Hibernate:更新标签集描述=?其中id =?

spring.jpa.properties.org.hibernate.flushMode=COMMIT

日志看起来像:

  

标记{id = 1,name =&#39; ffadsfasd&#39;,description =&#39; dasfadsgaaer&#39;,articles = []}
  Hibernate:更新标签集描述=?其中id =?

如果我上面说的问题,改变flushMode并不是一个好主意,除非它适合你的情况。您最好重构代码以获得更好的设计。

信息可以帮助您: