【发布时间】:2015-03-27 11:54:51
【问题描述】:
问题
dao/repository 方法、实体对象或实体 ID 的参数类型的最佳实践是什么?
示例代码
@Entity
class Product {
// ...
@ManyToOne
Seller seller;
}
@Entity
class Seller {
@Id @GeneratedValue
Long id;
}
class ProductDao {
// ...
// Using ids
public List<Product> getProductsOf(long sellerId) {
return getSession()
.createQuery("from Product where seller.id = ?")
.setLong(0, sellerId)
.list();
}
// Using object-references
public List<Product> getProductsOf(Seller seller) {
return getSession()
.createQuery("from Product where seller = ?")
.setEntity(0, seller)
.list();
}
// Using object-references using merge() on a detached object
public List<Product> getProductsOf2(Seller seller) {
Seller persistentSeller = getSession().merge(seller);
return getSession()
.createQuery("from Product where seller = ?")
.setEntity(0, seller)
.list();
}
// Using object-references using lock() on a detached object
public List<Product> getProductsOf3(Seller seller) {
getSession().buildLockRequest(LockOptions.NONE).lock(seller);
return getSession()
.createQuery("from Product where seller = ?")
.setEntity(0, seller)
.list();
}
}
优点和缺点
我发现了以下优点和缺点,但我想知道在经验丰富的 Spring/Hibernate/JPA 用户中是否有最佳实践。
优点:getProductsOf(Seller Seller)
- 当您已经有一个处于持久上下文(持久状态)的卖家时,从客户的角度来看很容易使用。
缺点:getProductsOf(Seller Seller)
- 您必须验证卖方是否处于持久或分离状态,这会使其实施变得冗长。您必须使用 merge() 或锁定,请参阅 getProductsOf2() 和 getProductsOf3()。
- 即使知道卖家的id,也得先单独查询卖家对象。 (load() 可用于使用代理来避免对卖方的额外查询,但您仍然必须调用会话对象。)
- 参数可以为空。
优点:getProductsOf(long SellerId)
- 如果您还没有卖方对象,但知道卖方 ID,那么当您只需要在工作单元中查询一次卖方 ID 时,这可能会更快。
- 避免空引用问题
缺点:getProductsOf(long SellerId)
- 当方法中存在多个“long”参数时,可能会导致参数调用顺序错误,导致使用错误的id进行查询。
- 感觉不像使用对象作为参数那样面向对象的方法。
- 方法调用看起来不太干净:
getProductsOf(seller.getId())
而不是:getProductsOf(seller)
我的偏好
我正在使用getProductsOf(Seller seller),但必须验证卖家是处于持久状态还是分离状态非常麻烦。因此,我正在考虑改用 id。
【问题讨论】:
-
我会说这取决于。如果您只想要一个对象的 id,则无需创建整个对象引用来设置 id 并将其作为参数传递。另一方面,如果您需要传递多个参数,请使用适当的对象引用。
-
当方法中存在多个“long”参数时,你可能会弄错参数调用顺序,导致你使用错误的id进行查询如果你遇到这种情况,我会说你的设计有问题。
标签: java hibernate jpa repository dao