将 Hibernate ORM 与 Panache 一起使用时的接口编码问题

问题描述

在 spring 中使用 hibernate 时,通常我们编码到如下界面

public interface UserRepository {
    Collection<User> findByLastName(String lastName) throws DataAccessException;
    //more methods
}

@Repository
public class JpaUserRepositoryImpl implements UserRepository {
    @PersistenceContext
    private EntityManager em;
    
    @SuppressWarnings("unchecked")
    public Collection<User> findByLastName(String lastName) {
        Query query = this.em.createquery("SELECT disTINCT user FROM User user  WHERE user.lastName LIKE :lastName");
        query.setParameter("lastName",lastName + "%");
        return query.getResultList();
    }
}
@Entity
@Table(name = "users")
public class User {
..
}

我们如何在 Panache 中做同样的事情?

public interface UserRepository extends PanacheRepositoryBase<User,Integer> {

    Collection<User> findByLastName(String lastName) ;
    //more methods
}

@ApplicationScoped
public class JpaUserRepositoryImpl implements UserRepository {

    @Inject
    private EntityManager em;

    @SuppressWarnings("unchecked")
    public Collection<User> findByLastName(String lastName) {
        Query query = this.em.createquery("SELECT disTINCT user FROM User user  WHERE user.lastName LIKE :lastName");
        query.setParameter("lastName",lastName + "%");
        return query.getResultList();
    }
}

它抛出

[2] Unsatisfied dependency for type javax.persistence.EntityManager and qualifiers [@Default]
        - java member: org....repository.jpa.JpaUserRepositoryImpl#em
        - declared on CLASS bean [types=[org....repository.jpa.JpaUserRepositoryImpl,org....repository.UserRepository,io.quarkus.hibernate.orm.panache.PanacheRepositoryBase<org.....model.User,java.lang.Integer>,java.lang.Object],qualifiers=[@Default,@Any],target=org.....repository.jpa.JpaUserRepositoryImpl]
[

解决方法

你可以让你的生活更轻松:

@ApplicationScoped
public class UserRepository implements PanacheRepository<User,Integer> {

   public List<User> findByLastName(String lastName) {
       return list("lastName",lastName);
   }
}

@ApplicationScoped
public class UserService {
    @Inject
    private UserRepository userRepository;

    @Transactional
    public List<User> findByLastName(String lastName) {
        return userRepository.findByLastName(lastName);
    }
}

使用 Panache,您实际上不需要使用此存储库模式(尽管您可以)。我现在喜欢的工作方式是这样的:

@Entity
// Because you have defined your own ID (Integer),you should extend PanacheEntityBase. If you don't have a specific reason for defining a custom ID,I'd recommend to extend PanacheEntity,you'll get a Long ID for free.
public class User extends PanacheEntity {
    public String lastName;
    
    public static List<User> findByLastName(String lastName) {
        return list("lastName",lastName);
    }
}

@ApplicationScoped
public class UserService {
    @Transactional
    public List<User> findByLastName(String lastName) {
        return User.findByLastName(lastName);
    }
}

请注意,当您使用 PanacheEntity 模式时,您应该将所有实例字段定义为“public”。 Panache 包装了这些字段,因此您将保留所需的封装! (所以如果你为这个字段定义了一个自定义的 setter,当有人这样做时,setter 将被调用:

user.lastName = "VanderLastName";

我不得不承认,我花了一段时间才习惯它。因此,特别是当您不想对您习惯的 (Spring) 进行太多更改时,您可能最好实施 Repository 模式。好消息:这完全是您自己的选择!

Quarkus 文档:https://quarkus.io/guides/hibernate-orm-panache