在JPA(Hibernate)中,當我們自動生成ID字段時,假定用戶不知道這個鍵。所以,在獲取實體時,用戶會根據ID以外的字段進行查詢。在這種情況下我們如何獲得實體(因爲不能使用em.find()
)。JPA:如何根據ID以外的字段值獲取實體?
我知道我們可以使用查詢並稍後過濾結果。但是,有沒有更直接的方法(因爲據我瞭解,這是一個非常普遍的問題)。
在JPA(Hibernate)中,當我們自動生成ID字段時,假定用戶不知道這個鍵。所以,在獲取實體時,用戶會根據ID以外的字段進行查詢。在這種情況下我們如何獲得實體(因爲不能使用em.find()
)。JPA:如何根據ID以外的字段值獲取實體?
我知道我們可以使用查詢並稍後過濾結果。但是,有沒有更直接的方法(因爲據我瞭解,這是一個非常普遍的問題)。
看一看:
JPA query language
:The Java Persistence Query LanguageJPA Criteria API
:Using the Criteria API to Create Queries它並不像你說這是一個 「問題」。
Hibernate具有內置find()
,但您必須構建自己的查詢才能獲取特定對象。我建議使用Hibernate的的Criteria
:
Criteria criteria = session.createCriteria(YourClass.class);
YourObject yourObject = criteria.add(Restrictions.eq("yourField", yourFieldValue))
.uniqueResult();
這將創建你的當前類中的criteria
,將限制該列‘yourField’等於價值yourFieldValue
。 uniqueResult()
告訴它帶來一個獨特的結果。如果更多的對象匹配,你應該檢索一個列表。
List<YourObject> list = criteria.add(Restrictions.eq("yourField", yourFieldValue)).list();
如果您還有其他問題,請隨時提問。希望這可以幫助。
寫這樣一個自定義的方法如下
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 = queryList.get(0);
}
return returnObject;
}
我不敢相信這麼簡單的東西有多少代碼。這是一個API失敗國際海事組織。 – 2014-05-13 20:52:42
使用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);
}
,並調用這樣的查找自定義的方法:
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();
}
如果您有實體Foo
的存儲庫並需要選擇所有條目與確切的字符串值boo
(也適用於其他基元類型或實體類型)。要把它放到你的資料庫界面:
List<Foo> findByBoo(String boo);
,如果您需要訂購的結果:
List<Foo> findByBooOrderById(String boo);
多見於reference。
您可以添加對此答案的引用嗎? – Jolley71717 2017-11-09 18:08:05
請注意,這隻適用於Spring,而不是Hibernate或JPA。 – Scadge 2017-12-11 13:07:38
我已經寫了一個庫,可以幫助做到這一點。它只允許通過僅初始化要過濾的字段進行搜索:https://github.com/kg6zvp/GenericEntityEJB
基本上,您應該添加特定的唯一字段。我通常使用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;
}
}
我認爲這裏缺少一些東西:'criteria.select(root);''root'定義在哪裏? – 2016-09-22 15:18:23
@JorgeCampos固定。謝謝。 – 2016-09-23 03:03:17
這很有幫助。謝謝。 – 2016-11-23 07:20:00
最佳做法是使用@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;
}
,讓我們的記錄,只需簡單地使用 'session.byNaturalId()'
Session session = sessionFactory.getCurrentSession();
User user = session.byNaturalId(User.class)
.using("email","[email protected]")
.load()
這是Hibernate的具體點嗎?我可以在JPA中使用它嗎? – Neo 2013-02-20 10:19:57
剛剛閱讀,這也可以與JPA一起使用。 – Neo 2013-02-20 10:35:24
'Criteria'是Hibernate特有的,因爲它來自'org.hibernate'包。 – 2013-02-20 12:14:29