gpt4 book ai didi

java - DAO 方法参数、对象引用与 id

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:25:16 25 4
gpt4 key购买 nike

问题

对于 dao/存储库方法、实体对象或实体 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() 可以使用代理代替,避免对 Seller 的额外查询,但您仍然必须调用 session 对象。)
  • 参数可以为空。

优点:getProductsOf(long sellerId)

  • 当您还没有卖家对象但知道 sellerId 时,如果您只需要在工作单元中查询一次 sellerId,这可能会更快。
  • 避免空引用问题

缺点:getProductsOf(long sellerId)

  • 当方法中存在多个“长”参数时,您可能会弄错参数调用顺序,导致您使用错误的id进行查询。
  • 与使用对象作为参数相比,感觉更像是一种面向对象的方法。
  • 方法调用看起来不太干净:
    getProductsOf(seller.getId())
    而不是:
    getProductsOf(卖家)

我的偏好

我正在使用 getProductsOf(Seller seller),但必须验证卖家是处于持久状态还是分离状态非常麻烦。因此,我正在考虑改用 ID。

最佳答案

最好的方法是避免写下你自己的 DAO 并使用 Spring Data相反。

我更喜欢 Spring Repository API,它看起来像这样:

public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> {
<S extends T> S save(S entity);

T findOne(ID primaryKey);

Iterable<T> findAll();

Long count();

void delete(T entity);

boolean exists(ID primaryKey);

}
  • savedelete 方法接受一个实体
  • findOneexists 采用标识符,因为它假定您没有要获取的实体

至于findOne,最好让它带一个标识符。这样即使你有一个实体也可以调用它。如果它是一个实体,那么您必须创建一个带有填充标识符的临时实体,只是为了获取关联的托管实体。

关于java - DAO 方法参数、对象引用与 id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28194683/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com