自定义Spring Boot Crud/JPA Repository查询报错求助
Spring Data JPA自定义Repository方法启动报错问题
问题情况
尝试用Crud/JPA Repository编写自定义数据库操作方法,启动时出现Bean创建失败的错误,同时在创建多操作的特定查询时也遇到问题。
相关代码
CartRepository
package com.example.registrationlogindemo.repository; import com.example.registrationlogindemo.model.Cart; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; public interface CartRepository extends CrudRepository<Cart,Long> { @Query(name = "INSERT INTO cart VALUES (:productID,:userID)",nativeQuery = true) List<Cart> save(@Param("productID") Long productId, @Param("userID") Long userID); @Query(name = "SELECT * FROM cart WHERE user_id = ?2",nativeQuery = true) List<Cart>showAll(Long productID, Long userID); }
Cart 实体类
package com.example.registrationlogindemo.model; import jakarta.persistence.*; import lombok.*; @Data @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "cart") public class Cart { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; }
CartController
@Controller public class CartController { private static SessionFactory factory; Long saveId; @Autowired ProductRepository productRepository; @Autowired UserRepository userRepository; CartRepository cartRepository; @GetMapping("/shoppingCart") @ResponseBody public String showCart(Model model, Principal principal){ String nume = principal.getName(); cartRepository.save(saveId,userRepository.AiciVoiAveaId(nume)); Optional<Product> product = productRepository.findById(saveId); model.addAttribute("product", product.get()); return "shoppingCart"; } @PostMapping("/shoppingCart/{id}") public String shoppingCart(@PathVariable Long id){ saveId = id; return "redirect:/shoppingCart"; } }
启动错误信息
2023-01-05T15:39:16.146+02:00 WARN 16652 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cartRepository' defined in com.example.registrationlogindemo.repository.CartRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract java.util.List com.example.registrationlogindemo.repository.CartRepository.save(java.lang.Long,java.lang.Long); Reason: Failed to create query for method public abstract java.util.List com.example.registrationlogindemo.repository.CartRepository.save(java.lang.Long,java.lang.Long); No property 'save' found for type 'Cart' org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cartRepository' defined in com.example.registrationlogindemo.repository.CartRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract java.util.List com.example.registrationlogindemo.repository.CartRepository.save(java.lang.Long,java.lang.Long); Reason: Failed to create query for method public abstract java.util.List com.example.registrationlogindemo.repository.CartRepository.save(java.lang.Long,java.lang.Long); No property 'save' found for type 'Cart'
问题分析与修复步骤
1. 核心错误原因
自定义的save方法和CrudRepository自带的save方法重名,Spring Data JPA会优先按照方法名规则解析(比如找实体的save属性),而不是使用你写的@Query注解,导致报错找不到对应属性。
2. 分步修复
(1)修正Cart实体类
你的Cart实体缺少数据库表对应的product_id和user_id字段,必须补上才能和SQL操作匹配:
package com.example.registrationlogindemo.model; import jakarta.persistence.*; import lombok.*; @Data @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "cart") public class Cart { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 对应数据库的product_id列 @Column(name = "product_id") private Long productId; // 对应数据库的user_id列 @Column(name = "user_id") private Long userId; }
(2)重构CartRepository
- 重命名自定义的save方法,避免和CrudRepository自带方法冲突
- 插入操作需要添加
@Modifying和@Transactional注解(写操作必须事务支持) @Query注解用value属性写SQL,不是name(name是指定命名查询的名称)- 修正
showAll方法的冗余参数和SQL逻辑
package com.example.registrationlogindemo.repository; import com.example.registrationlogindemo.model.Cart; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Repository public interface CartRepository extends CrudRepository<Cart,Long> { // 自定义添加购物项方法,返回影响行数 @Modifying @Transactional @Query(value = "INSERT INTO cart (product_id, user_id) VALUES (:productId, :userId)", nativeQuery = true) int addCartItem(@Param("productId") Long productId, @Param("userId") Long userId); // 根据用户ID查询所有购物项 @Query(value = "SELECT * FROM cart WHERE user_id = :userId", nativeQuery = true) List<Cart> findAllByUserId(@Param("userId") Long userId); }
(3)修正CartController
- 给cartRepository添加
@Autowired注解完成注入 - 调用重命名后的
addCartItem方法
@Controller public class CartController { private static SessionFactory factory; Long saveId; @Autowired ProductRepository productRepository; @Autowired UserRepository userRepository; @Autowired // 补上注入注解 CartRepository cartRepository; @GetMapping("/shoppingCart") @ResponseBody public String showCart(Model model, Principal principal){ String nume = principal.getName(); Long userId = userRepository.AiciVoiAveaId(nume); // 调用自定义的添加方法 cartRepository.addCartItem(saveId, userId); Optional<Product> product = productRepository.findById(saveId); model.addAttribute("product", product.get()); return "shoppingCart"; } @PostMapping("/shoppingCart/{id}") public String shoppingCart(@PathVariable Long id){ saveId = id; return "redirect:/shoppingCart"; } }
3. 额外注意点
- 如果需要执行多操作的查询(比如批量插入/更新),同样需要
@Modifying和@Transactional注解,并且确保SQL语句正确 - 尽量遵循Spring Data JPA的方法命名规则(比如
findAllByUserId),很多时候不需要写原生SQL,框架会自动生成查询语句
内容的提问来源于stack exchange,提问作者Ovidiu
相关产品推荐
相关产品推荐

