JPA:如何根据ID以外的字段值获取实体?

Neo*_*Neo 48 java hibernate jpa

在JPA(Hibernate)中,当我们自动生成ID字段时,假设用户不知道该密钥.因此,当获得实体时,用户将基于除ID之外的某些字段进行查询.在这种情况下我们如何获得实体(因为em.find()不能使用).

我知道我们可以使用查询并稍后过滤结果.但是,是否有更直接的方式(因为这是我理解的一个非常常见的问题).

Rau*_*ene 33

这不是你所说的"问题".

Hibernate具有内置功能find(),但您必须构建自己的查询才能获取特定对象.我推荐使用HibernateCriteria:

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

这将criteria在您当前的类上创建一个,添加"yourField"列等于该值的限制yourFieldValue.uniqueResult()告诉它带来一个独特的结果.如果更多对象匹配,则应检索列表.

List<YourObject> list = criteria.add(Restrictions.eq("yourField", yourFieldValue)).list();
Run Code Online (Sandbox Code Playgroud)

如果您有任何其他问题,请随时提出.希望这可以帮助.

  • 你可以原谅我的新手问题:什么是会话实例? (6认同)

cic*_*ici 18

如果您有实体的存储库,Foo并且需要选择具有精确字符串值的所有条目boo(也适用于其他基本类型或实体类型).把它放到你的存储库界面:

List<Foo> findByBoo(String boo);
Run Code Online (Sandbox Code Playgroud)

如果您需要订购结果:

List<Foo> findByBooOrderById(String boo);
Run Code Online (Sandbox Code Playgroud)

查看更多的参考.

  • 请注意,这仅适用于Spring,而不适用于Hibernate或JPA. (9认同)

Jin*_*won 8

基本上,您应该添加一个特定的唯一字段.我通常使用xxxUri字段.

class User {

    @Id
    // automatically generated
    private Long id;

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

你的业务方法会这样做.

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


rom*_*ucr 8

我解决了一个类似的问题,我想通过 isbnCode 而不是你的 id(主键)来查找一本书。

@Entity
public class Book implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private String isbnCode;

...
Run Code Online (Sandbox Code Playgroud)

在存储库中,该方法是像 @kamalveer singh 提到的那样创建的。请注意,方法名称是 findBy+fieldName (在我的例子中:findByisbnCode):

@Repository
public interface BookRepository extends JpaRepository<Book, Integer> {

    Book findByisbnCode(String isbnCode);
}
Run Code Online (Sandbox Code Playgroud)

然后,在服务中实现该方法:

@Service
public class BookService {

    @Autowired
    private BookRepository repo;
    
    
    public Book findByIsbnCode(String isbnCode) {
        Book obj = repo.findByisbnCode(isbnCode);
        return obj; 
    }
}
Run Code Online (Sandbox Code Playgroud)


Che*_*胡晨海 7

最佳实践是使用 @NaturalId 注释。在某些情况下它可以用作业务键它太复杂了,因此在现实世界中将某些字段用作标识符。例如,我有一个以用户 ID 作为主键的用户类,电子邮件也是唯一的字段。所以我们可以使用电子邮件作为我们的自然 ID

@Entity
@Table(name="user")
public class User {
  @Id
  @Column(name="id")
  private int id;

  @NaturalId
  @Column(name="email")
  private String email;

  @Column(name="name")
  private String name;
}
Run Code Online (Sandbox Code Playgroud)

要获得我们的记录,只需简单地使用 'session.byNaturalId()'

Session session = sessionFactory.getCurrentSession();
User user = session.byNaturalId(User.class)
                   .using("email","huchenhai@qq.com")
                   .load()
Run Code Online (Sandbox Code Playgroud)


J A*_*rov 5

这个解决方案来自Beginning Hibernate书:

     Query<User> query = session.createQuery("from User u where u.scn=:scn", User.class);
     query.setParameter("scn", scn);
     User user = query.uniqueResult();    
Run Code Online (Sandbox Code Playgroud)


Wil*_*leu 0

看一下: