What is the best practice for the type of paramaters of dao/repository method, entity-objects or entity-ids?
@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();    
    }
}
I have found the following pros and cons, but I was wondering if there is a best practice among experienced Spring/Hibernate/JPA users.
getProductsOf(seller.getId())getProductsOf(seller)
I'm using getProductsOf(Seller seller), but having to verify whether seller is in persistent or detached state is very cumbersome. Therefor, I'm thinking of using ids instead.
The best way is to avoid writing down your own DAO and use Spring Data instead.
I prefer the Spring Repository API, which looks like this:
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);
}
save and delete methods take an entityfindOne and exists take an identifier because it assumes you don't have the entity that you want to fetchAs for findOne, it's better to have it take an identifier. This way you can call it even if you have an entity. If it were taken an entity, then you'd have to create a transient entity with a populated identifier just for the sake of fetching the associated managed entity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With