Spring JPA / Hibernate вызывает полное обновление перед специальным обновлением, используя @Modifying и @Query - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть весенний репозиторий для класса Business:

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 голосов
/ 27 апреля 2018
@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

журнал выглядит так:

Tag {id = 1, name = 'ffadsfasd', description = 'dasfadsg', article = []}
Hibernate: обновить описание набора тегов = ?, name =? где id =?
Hibernate: обновить описание набора тегов =? где id =?

при spring.jpa.properties.org.hibernate.flushMode=COMMIT

журнал выглядит так:

Tag {id = 1, name = 'ffadsfasd', description = 'dasfadsgaaer', article = []}
Hibernate: обновить описание набора тегов =? где id =?


Если проблема в том, что я сказал выше, не стоит менять flushMode, если это не подходит для вашей ситуации. Вы бы лучше рефакторинг вашего кода для лучшего дизайна.


информация может вам помочь:

...