代码之家  ›  专栏  ›  技术社区  ›  en Peris

spring data jpa:插入而不是删除

  •  0
  • en Peris  · 技术社区  · 7 年前

    我有一个基本的SpringBoot应用程序。使用spring初始化器、jpa、嵌入式tomcat、thymeleaf模板引擎,并将其打包为一个可执行的jar文件。我已创建此存储库类:

    @Repository
    public interface MenuRepository extends CrudRepository<Menu, Long> {
    
          @Cacheable("menus")
          @Query("select cur from Menu cur where cur.MenuId = ?1")
          Menu findMenuByMenuId (String MenuId);
    
          @Cacheable("menus")
          @Query("select cur from Menu cur where lower (cur.symbol) = lower (?1) ")
          Menu findMenuBySymbol (String symbol);
    

    这项服务:

    @Service
    public class MenuService {
    
            @Autowired
        protected MenuRepository menuRepository;    
    
        @Autowired
        MenuPriceService menuPriceService;
    
    
         @Transactional
         public Menu save (Menu menu) {              
             return menuRepository.save (menu);
         }
    
    
         @Transactional
         public void delete (Menu menu) {
             menuRepository.delete  (menu);
         }
         ..
    }
    
    
    }
    

    这个junit测试:

        @Test
        @Transactional
        public void testDelete () {
    
            String menuName = System.currentTimeMillis()+"";
    
            Menu menu = new Menu(); 
            menu.setMenuId(menuName);
            menuService.delete (menu);
    }
    

    但这是我在控制台上看到的

    Hibernate: 
        insert 
        into
            t_menu
            (...) 
        values
            (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Jens Schauder    7 年前

    移除时 @Transactional as suggested in another answer 可能会使行为消失,我会质疑测试的有效性。

    问题是:为什么要删除不在数据库中的实体?

    解决方案:

    如果模拟不知道实体是否存在的情况,请使用 deleteById 当id不在数据库中时,它将抛出一个异常,当然,您可以捕获它。

    关于插入的方式和原因的一些背景知识:

    delete(T entity) 是通过 SimpleJpaRepository.delete(T entity) 基本上包含了这一行代码。

    em.remove(em.contains(entity) ? entity : em.merge(entity));
    

    正如你所看到的 merge 如果实体不在 EntityManager . 没有 合并 如果会话中存在具有相同类和ID的另一个实例 实体管理器 . 但由于您的实体根本不存在,这会触发对数据库的插入。

    你可能会这样想:你创建一个实例,然后 实体管理器 了解它(通过告诉它删除它)并将其删除,因此需要在数据库中执行以下步骤->插入+删除。

        2
  •  0
  •   Nuñito Calzada    7 年前

    去除 @Transactional :

    @Test
        public void testDelete () {
    
            String menuName = System.currentTimeMillis()+"";
    
            Menu menu = new Menu(); 
            menu.setMenuId(menuName);
            menuService.delete (menu);
    }