【发布时间】:2018-11-21 21:45:48
【问题描述】:
我有一个基本的 SpringBoot 应用程序。使用 Spring Initializer、JPA、嵌入式 Tomcat、Thymeleaf 模板引擎,并将其打包为可执行的 JAR 文件。 我已经创建了这个 Repository 类:
@Repository
public interface MenuRepository extends CrudRepository<Menu, Long> {
..
}
还有这个服务类
@Service
@Transactional(readOnly = true)
public class MenuService {
@Autowired
protected MenuRepository menuRepository;
@Transactional
public void delete (Menu menu) {
menuRepository.delete (menu);
}
..
}
还有这个 Junit 测试:
@ContextConfiguration(classes={TestSystemConfig.class})
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MenuGestApplication.class)
public class MenuServiceTests {
...
@Test
public void testDelete () {
Menu menu = new menu();
menu.setmenuId("bacalla-amb-tomaquet");
menuService.save(menu);
MenuPrice menuPrice = new menuPrice(menu);
menuPrice.setPrice((float)20.0);
menuPriceService.save(menuPrice);
MenuPriceSummary menuPriceSummary = new menuPriceSummary(menu);
menuPriceSummary.setFortnightlyAvgPrice((float)20.0);
menuPriceSummaryService.save(menuPriceSummary);
menu = menuService.findBymenuId("bacalla-amb-tomaquet");
assertNotNull (menu);
menuService.delete (menu);
menu = menuService.findBymenuId("bacalla-amb-tomaquet");
assertNull (menu);
}
}
但是 Junit 失败了,因为对象没有被删除并且没有抛出异常!
正如建议的那样,我在属性中有这个..
@OneToMany(mappedBy="menu", cascade = CascadeType.ALL, orphanRemoval = true, fetch=FetchType.LAZY)
private List<MenuPrice> price;
即使我在运行测试时在控制台中看到了这一点:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`elcormenu`.`t_menu_price`, CONSTRAINT `FK19d0sljpshu4g8wfhrkqj7j7w` FOREIGN KEY (`menu_id`) REFERENCES `t_menu` (`id`))
和菜单类:
@Entity
@Table(name="t_menu")
public class Menu implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty("id")
private Long id;
@JsonProperty("MenuId")
private String MenuId;
@OneToMany(mappedBy = "Menu", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@JsonIgnore
private Set<MenuPrice> MenuPrice = new HashSet<>();
@OneToOne(mappedBy = "Menu", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JsonIgnore
private MenuPriceSummary summary;
...
}
【问题讨论】:
-
为什么不使用菜单实体的主键删除?
-
菜单实体是什么样子的?特别是 id 生成?
-
MenuPrice 上对 Menu 的引用有什么注释? @ManyToOne?你能显示两个实体的代码吗?
-
不要在
@ManyToOne关系上添加cascade = CascadeType.ALL。如果您确实删除了 MenuPrice 将尝试删除它的 Menu,这将尝试删除它的所有 MenuPrices。仅应用最低限度的 CascadeType 会更安全。我也会避免修改默认的 FetchType。
标签: java spring-mvc spring-boot junit junit4