Groovy 和 JPA 阻止 Spring Boot CrudRepository 进行插入

Posted

技术标签:

【中文标题】Groovy 和 JPA 阻止 Spring Boot CrudRepository 进行插入【英文标题】:Groovy and JPA preventing Spring Boot CrudRepository from doing inserts 【发布时间】:2018-01-06 03:43:25 【问题描述】:

我有一个(Groovy)Spring Boot 应用程序,它与 H2 内存数据库通信(但不认为这很重要)。我有以下GroceryItem 实体:

@MappedSuperclass
abstract class BaseEntity 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id


@Canonical
@TupleConstructor(includeSuperProperties = true)
@ToString(includeSuperProperties = true)
@Entity(name = 'grocery_items')
@AttributeOverrides([
        @AttributeOverride(name = "id", column=@Column(name="grocery_item_id"))
])
class GroceryItem extends BaseEntity 
    @Column(name = 'grocery_item_name')
    @NotNull
    @Valid
    String name

    @Column(name = 'grocery_item_qty')
    @NotNull
    Integer quantity

然后是一个CrudRepository 接口:

interface GroceryItemPersistor extends CrudRepository<GroceryItem, Long> 
    @Query('FROM grocery_items WHERE grocery_item_name = :name')
    GroceryItem findByName(@Param('name') String name)

    @Query('FROM grocery_items')
    List<GroceryItem> getAllGroceries()

但是由于某种原因,这个CrudRepositorysave(...) 方法只是更新并允许我将一个GroceryItem 插入到数据库中。意思是如果我运行这段代码:

GroceryItem olives = new GroceryItem(1L, '123456', 'Olives', 6)
groceryItemPersistor.save(olives)

List<GroceryItem> allItems = groceryItemPersistor.getAllGroceries()
log.info("There are $allItems.size() grocery items.")
log.info("$allItems.first().name are in there right now")

GroceryItem cheeseWedges = new GroceryItem(2L, '067e6162-3b6f-4ae2-a171-2470b63dff00', 'Cheese Wedges', 4)
groceryItemPersistor.save(cheeseWedges)

allItems = groceryItemPersistor.getAllGroceries()
log.info("There are $allItems.size() grocery items.")
log.info("$allItems.first().name are in there right now")

我在控制台上得到以下输出:

There are 1 grocery items.
Olives are in there right now.
There are 1 grocery items.
Cheese Wedges are in there right now.

我必须在我的GroceryItem 和/或BaseEntity 类中修改什么才能使save(...) 正确插入而不是更新?

【问题讨论】:

【参考方案1】:

创建主键为 1 的橄榄项后,您在创建 cheeseWedges 时传递了相同的主键。

GroceryItem cheeseWedges = new GroceryItem(1L, '067e6162-3b6f-4ae2-a171-2470b63dff00', 'Cheese Wedges', 4)

尝试创建新项目时不要设置主键。如果您设置它,JPA 将尝试更新表中具有相同主键的项目。

【讨论】:

感谢@Ishan (+1) 非常 很抱歉这里的混乱,但我犯了 critical 复制-n-粘贴错误。请看我的编辑!我 am 使用 不同 主键 (2L) 保存“Cheese Wedge”,但 JPA/Hibernate/Spring 仍然只允许保存/更新单个项目。 【参考方案2】:

我想通了。我正在创建一个主键并保存它,而不是让 JPA 在调用save 时为我创建我的@Generated 键。将我的实体实例更改为具有null id:

GroceryItem bananas = new GroceryItem(null, '067e6162-3b6f-4ae2-a171-2470b63dff00', 'Bananas', 12)

...修复了这个问题。

【讨论】:

以上是关于Groovy 和 JPA 阻止 Spring Boot CrudRepository 进行插入的主要内容,如果未能解决你的问题,请参考以下文章

当加载 spring-boot 和 spring-data-jpa 时,Hibernate 无法加载 JPA 2.1 Converter

Kotlin,Spring Boot,JPA - 获取通用枚举的值 (E.valueOf(stringValue))

JPA配置,简单使用以及常见问题

Spring JPA - 准备好的语句查询?

Spring数据休息 - 是否存在阻止所有删除操作的全局开关?

Groovy:使用 Grails 和 Spring 安全核心插件时出现意外令牌