DAO方法参数,对象引用vs ids

Dev*_*abc 6 java dao hibernate jpa repository

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();    
    }
}
Run Code Online (Sandbox Code Playgroud)

利弊

我发现了以下优点和缺点,但我想知道有经验的Spring/Hibernate/JPA用户是否有最佳实践.

优点:getProductsOf(卖方卖家)

  • 当您已经拥有处于持久上下文(持久状态)的卖方时,从客户角度来看易于使用.

缺点:getProductsOf(卖方卖家)

  • 您必须验证卖家处于持久或分离状态,这可能使其实施冗长.您必须使用merge()或锁定,请参阅getProductsOf2()和getProductsOf3().
  • 即使您知道卖家的ID,您首先必须分别查询卖家对象.(load()可以用来代替使用代理来避免对Seller的额外查询,但你仍然需要调用session对象.)
  • 参数可以为null.

优点:getProductsOf(long sellerId)

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

缺点:getProductsOf(long sellerId)

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

我的偏好

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

Vla*_*cea 2

最好的方法是避免编写自己的 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);

}
Run Code Online (Sandbox Code Playgroud)
  • save方法delete采用一个实体
  • 并采用标识符findOneexists因为它假设您没有要获取的实体

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