[英]Can I use only Entity's id instead of fetching an entity from DB when there is a relationship in an Entity?
I am using Spring Data JPA with Hibernate.我正在使用 Spring 数据 JPA 和 Hibernate。
Lets say I have the following entity defined:假设我定义了以下实体:
@Entity
@Table(name = "foods")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "food_id")
private Long foodId;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "food_type_id")
@NotNull
private FoodType foodType;
...
}
@Entity
@Table(name = "food_types")
public class FoodType {
public static final Integer PERISHABLE;
public static final Integer NON_PERISHABLE;
@Id
@Column(name = "food_type")
private Integer foodTypeId;
private String name;
...
}
Every time when I want to create a Food
entity and save it to the database, currently code looks like this:每次我想创建一个Food
实体并将其保存到数据库时,当前代码如下所示:
Food food = new Food();
FoodType foodType = foodTypeRepository.findById(FoodType.PERISHABLE); // Call to DB to get Entity
food.setFoodType(foodType);
....
foodRepository.save(food);
If we consider FoodType to be constant in the DB.如果我们认为 FoodType 在数据库中是常量。 Can I use it like this:我可以这样使用它:
Food food = new Food();
FoodType foodType = new FoodType();
foodType.setFoodTypeId(FoodType.PERISHABLE); // No Call to DB
food.setFoodType(foodType);
....
foodRepository.save(food);
I have tested it and yes I can use it that way, hibernate will save the Food
entity, but are there any downsides, pitfalls, etc... I am not seeing.我已经对其进行了测试,是的,我可以这样使用它,hibernate 将保存Food
实体,但是否有任何缺点、陷阱等……我没有看到。
PS. PS。 This is just a simple example illustrating the idea, it is part of old legacy project which I cannot modify to remove constant from DB, and use an enum instead.这只是一个说明这个想法的简单示例,它是旧遗留项目的一部分,我无法修改它以从数据库中删除常量,而是使用枚举。
To avoid extra call to DB you should use:为避免额外调用 DB,您应该使用:
FoodType foodType = foodTypeRepository.getOne(FoodType.PERISHABLE);
under the hood it calls EntityManager.getReference
that obtain a reference to an entity without having to load its data as opposed to the foodTypeRepository.findById
that lead to call EntityManager.find
that obtain an entity along with its data .在引擎盖下,它调用EntityManager.getReference
获得对实体的引用,而无需加载其数据,而不是导致调用EntityManager.find
的foodTypeRepository.findById
获得实体及其数据。
See also this section of the hibernate documentation.另请参阅 hibernate 文档的此部分。
PS You can not use: PS你不能使用:
Food food = new Food();
FoodType foodType = new FoodType();
foodType.setFoodTypeId(FoodType.PERISHABLE);
as in this case hibernate consider foodType
as a transient entity (not associated with a persistence context ) and will try to save it as a new record if you have a proper cascading on your @ManyToOne
association.在这种情况下 hibernate 将foodType
视为一个临时实体(与持久性上下文无关),如果您在@ManyToOne
关联上有适当的级联,将尝试将其保存为新记录。
PSS As it's mentioned in the documentation the method JpaRepository#getOne(ID)
is deprecated and you should use JpaRepository#getById(ID)
instead. PSS 正如文档中提到的那样,方法JpaRepository#getOne(ID)
已被弃用,您应该改用JpaRepository#getById(ID)
。
You do not need to fetch the entity associated with FoodType.PERISHABLE
in order to set the relation on a Food
entity to it and I'm not aware of any side effects or pitfalls of using FoodType.PERISHABLE
directly as long it is a valid FoodType
id.您无需获取与FoodType.PERISHABLE
关联的实体即可将Food
实体上的关系设置为它,而且我不知道直接使用FoodType.PERISHABLE
的任何副作用或陷阱,只要它是有效的FoodType
ID。
As others mentioned, you could also use JpaRepository#getById(ID id) and that's probably the more canonical way of addressing this problem:正如其他人提到的,您也可以使用JpaRepository#getById(ID id)这可能是解决此问题的更规范的方法:
T getById(ID id) Returns a reference to the entity with the given identifier. T getById(ID id) 返回对具有给定标识符的实体的引用。 Depending on how the JPA persistence provider is implemented this is very likely to always return an instance and throw an EntityNotFoundException on first access.根据 JPA 持久性提供程序的实现方式,这很可能总是返回一个实例并在首次访问时抛出 EntityNotFoundException。 Some of them will reject invalid identifiers immediately.他们中的一些人会立即拒绝无效的标识符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.