Mas*_*r_T 10 java sql hibernate jpa
我的Web应用程序中有一个管理控制台,允许管理员在我们的数据库上执行自定义SQL SELECT查询.
在下面,应用程序正在使用Hibernate,但这些查询不是HQL,它们是纯SQL,所以我使用这样的Native Query:
protected EntityManager em;
public List<Object[]> execute(String query) {
Query q = em.createNativeQuery(query);
List<Object[]> result = q.getResultList();
return result;
}
Run Code Online (Sandbox Code Playgroud)
这可以正常工作,但它只返回数据行,没有额外的信息.我想要的是获取列名,所以当我将结果打印回给用户时,我也可以打印一个标题来显示各列的内容.
有没有办法做到这一点?
gee*_*kfa 19
Query query = entityManager.createNamedQuery(namedQuery);
NativeQueryImpl nativeQuery = (NativeQueryImpl) query;
nativeQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<Map<String,Object>> result = nativeQuery.getResultList();
Run Code Online (Sandbox Code Playgroud)
现在你有了Map<String,Object>。您可以看到您的列名称
小智 7
这段代码对我有用
DTO 类:
public class ItemResponse<T> {
private T item;
public ItemResponse() {
}
public ItemResponse(T item) {
super();
this.item = item;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
Run Code Online (Sandbox Code Playgroud)
服务等级如下
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Service;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
@Service
public class ServiceClass{
@PersistenceContext
public EntityManager entityManager;
public ItemResponse exceuteQueryResponse(String queryString) {
ItemResponse itemResponse=new ItemResponse();
Query jpaQuery = entityManager.createNativeQuery(queryString);
org.hibernate.Query hibernateQuery =((org.hibernate.jpa.HibernateQuery)jpaQuery).getHibernateQuery();
hibernateQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<Map<String,Object>> res = hibernateQuery.list();
itemResponse.setItem(res);
return itemResponse;
}
}
Run Code Online (Sandbox Code Playgroud)
2020年
使用 hibernate 5.2.11.Final 实际上很容易。在我的示例中,您可以看到我如何获取每一行的列名。以及我如何按列名获取值。
Query q = em.createNativeQuery("SELECT columnA, columnB FROM table");
List<Tuple> result = q.getResultList();
for (Tuple row: result){
// Get Column Names
List<TupleElement<Object>> elements = row.getElements();
for (TupleElement<Object> element : elements ) {
System.out.println(element.getAlias());
}
// Get Objects by Column Name
Object columnA;
Object columnB;
try {
columnA = row.get("columnA");
columnB= row.get("columnB");
} catch (IllegalArgumentException e) {
System.out.println("A column was not found");
}
}
Run Code Online (Sandbox Code Playgroud)
Ryiad 的回答 DTO 增加了一些混乱,你应该把它远离。您应该已经解释过它仅适用于休眠。
如果像我一样您需要保持列的顺序,您可以指定您自己的变压器。我从hibernate复制了代码并将HashMap更改为LinkedHashMap:
import java.util.LinkedHashMap;
import java.util.Map;
import org.hibernate.transform.AliasedTupleSubsetResultTransformer;
import org.hibernate.transform.ResultTransformer;
/**
* {@link ResultTransformer} implementation which builds a map for each "row", made up of each aliased value where the
* alias is the map key. Inspired by {@link org.hibernate.transform.AliasToEntityMapResultTransformer}, but kepping the
* ordering of elements.
* <p/>
* Since this transformer is stateless, all instances would be considered equal. So for optimization purposes we limit
* it to a single, singleton {@link #INSTANCE instance}.
*/
public class AliasToEntityMapResultTransformer extends AliasedTupleSubsetResultTransformer {
public static final AliasToEntityMapResultTransformer INSTANCE = new AliasToEntityMapResultTransformer();
/**
* Disallow instantiation of AliasToEntityMapResultTransformer.
*/
private AliasToEntityMapResultTransformer() {
}
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
Map result = new LinkedHashMap<>(tuple.length);
for (int i = 0; i < tuple.length; i++) {
String alias = aliases[i];
if (alias != null) {
result.put(alias, tuple[i]);
}
}
return result;
}
@Override
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
return false;
}
/**
* Serialization hook for ensuring singleton uniqueing.
*
* @return The singleton instance : {@link #INSTANCE}
*/
private Object readResolve() {
return INSTANCE;
}
}
Run Code Online (Sandbox Code Playgroud)
有了这个变压器,您可以将 Ryiad 的解决方案与 Hibernate 结合使用:
Query jpaQuery = entityManager.createNativeQuery(queryString);
org.hibernate.Query hibernateQuery =((org.hibernate.jpa.HibernateQuery)jpaQuery).getHibernateQuery();
hibernateQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<Map<String,Object>> res = hibernateQuery.list();
Run Code Online (Sandbox Code Playgroud)
很长一段时间没有任何答案,并且根据我自己的进一步研究,似乎这是不可能的,不幸的是。
| 归档时间: |
|
| 查看次数: |
7669 次 |
| 最近记录: |