79

JPA (Hibernate) では、ID フィールドを自動的に生成するとき、ユーザーはこのキーについて何も知らないと見なされます。したがって、エンティティを取得するとき、ユーザーは ID 以外のフィールドに基づいてクエリを実行します。その場合、どのようにエンティティを取得しますか (em.find()使用できないため)。

クエリを使用して、後で結果をフィルタリングできることを理解しています。しかし、もっと直接的な方法はありますか (私が理解しているように、これは非常に一般的な問題であるため)。

4

15 に答える 15

44

あなたが言ったように、それは「問題」ではありません。

Hibernate には が組み込まれてfind()いますが、特定のオブジェクトを取得するには、独自のクエリを作成する必要があります。Hibernateの使用をお勧めしCriteriaます:

Criteria criteria = session.createCriteria(YourClass.class);
YourObject yourObject = criteria.add(Restrictions.eq("yourField", yourFieldValue))
                             .uniqueResult();

これによりcriteria、現在のクラスに が作成され、列「yourField」が value と等しいという制限が追加されますyourFieldValueuniqueResult()ユニークな結果をもたらすように指示します。より多くのオブジェクトが一致する場合は、リストを取得する必要があります。

List<YourObject> list = criteria.add(Restrictions.eq("yourField", yourFieldValue)).list();

ご不明な点がございましたら、お気軽にお問い合わせください。お役に立てれば。

于 2013-02-20T10:09:07.673 に答える
10

基本的に、特定の一意のフィールドを追加する必要があります。私は通常xxxUriフィールドを使用します。

class User {

    @Id
    // automatically generated
    private Long id;

    // globally unique id
    @Column(name = "SCN", nullable = false, unique = true)
    private String scn;
}

そして、あなたのビジネスメソッドはこのようになります。

public User findUserByScn(@NotNull final String scn) {
    CriteriaBuilder builder = manager.getCriteriaBuilder();
    CriteriaQuery<User> criteria = builder.createQuery(User.class);
    Root<User> from = criteria.from(User.class);
    criteria.select(from);
    criteria.where(builder.equal(from.get(User_.scn), scn));
    TypedQuery<User> typed = manager.createQuery(criteria);
    try {
        return typed.getSingleResult();
    } catch (final NoResultException nre) {
        return null;
    }
}
于 2016-07-13T04:14:50.147 に答える
4

次のようなカスタム メソッドを記述します。

public Object findByYourField(Class entityClass, String yourFieldValue)
{
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery(entityClass);
    Root<Object> root = criteriaQuery.from(entityClass);
    criteriaQuery.select(root);

    ParameterExpression<String> params = criteriaBuilder.parameter(String.class);
    criteriaQuery.where(criteriaBuilder.equal(root.get("yourField"), params));

    TypedQuery<Object> query = entityManager.createQuery(criteriaQuery);
    query.setParameter(params, yourFieldValue);

    List<Object> queryResult = query.getResultList();

    Object returnObject = null;

    if (CollectionUtils.isNotEmpty(queryResult)) {
        returnObject = queryResult.get(0);
    }

    return returnObject;
}
于 2013-02-20T10:36:21.630 に答える
1

いいえ、基準クエリを作成する必要はありません。Spring-boot で作業している場合は、定型コードになります。レポで、findBy[正確なフィールド名] を使用してメソッド名を宣言します。例-モデルまたはドキュメントが文字列フィールドmyField で構成されていて、それで検索したい場合、メソッド名は次のようになります。

findBymyField(String myField);

于 2020-05-01T08:32:14.080 に答える
1

All the answers require you to write some sort of SQL/HQL/whatever. Why? You don't have to - just use CriteriaBuilder:

Person.java:

@Entity
class Person  {
  @Id @GeneratedValue
  private int id;

  @Column(name = "name")
  private String name;
  @Column(name = "age")
  private int age;
  ...
}

Dao.java:

public class Dao  {
  public static Person getPersonByName(String name)  {
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        
        CriteriaBuilder cb = session.getCriteriaBuilder();
        
        CriteriaQuery<Person> cr = cb.createQuery(Person.class);
        Root<Person> root = cr.from(Person.class);
        cr.select(root).where(cb.equal(root.get("name"), name));  //here you pass a class field, not a table column (in this example they are called the same)

        Query query = session.createQuery(cr);
        query.setMaxResults(1);
        List<Person> resultList = query.getResultList();

        Person result = resultList.get(0);
        
        return result;
  }
}

example of use:

public static void main(String[] args)  {
  Person person = Dao.getPersonByName("John");
  System.out.println(person.getAge());  //John's age
}
于 2019-12-16T17:51:04.017 に答える
0

見て:

于 2013-02-20T10:07:54.263 に答える
0

これを正確に行うのに役立つライブラリを作成しました。フィルタリングするフィールドのみを初期化するだけで、オブジェクトによる検索が可能になります: https://github.com/kg6zvp/GenericEntityEJB

于 2016-06-13T08:49:53.750 に答える
0

私のSpring Bootアプリでは、次のような同様の問題を解決しました:

@Autowired
private EntityManager entityManager;

public User findByEmail(String email) {
    User user = null;
    Query query = entityManager.createQuery("SELECT u FROM User u WHERE u.email=:email");
    query.setParameter("email", email);
    try {
        user = (User) query.getSingleResult();
    } catch (Exception e) {
        // Handle exception
    }
    return user;
}
于 2019-02-04T21:29:34.760 に答える
-2

CrudRepository と JPA クエリを使用するとうまくいきます。

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

public interface TokenCrudRepository extends CrudRepository<Token, Integer> {

 /**
 * Finds a token by using the user as a search criteria.
 * @param user
 * @return  A token element matching with the given user.
 */
    @Query("SELECT t FROM Token t WHERE LOWER(t.user) = LOWER(:user)")
    public Token find(@Param("user") String user);

}

そして、次のように find カスタム メソッドを呼び出します。

public void destroyCurrentToken(String user){
    AbstractApplicationContext context = getContext();

    repository = context.getBean(TokenCrudRepository.class);

    Token token = ((TokenCrudRepository) repository).find(user);

    int idToken = token.getId();

    repository.delete(idToken);

    context.close();
}
于 2014-03-24T23:03:08.933 に答える