在使用Spring Data JPA进行数据库查询的场景下,经常需要进行结果的映射,不仅加大了工作量,而且编写出来的代码很丑陋,看到那种代码就不想去维护。
以下是本人编写的一个通用型的函数,或可解决这一问题:
环境:spring jpa2.0.8 hibernate-core 5.2.17.Final
package com.cec.dao;
import com.cec.bind.BeanCreater;
import com.cec.exception.CustomException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.hibernate.Session;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.hibernate.type.*;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.persistence.EntityManager;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
/**
* Created by Trace on 2018-07-24.<br/>
* Desc: entityManager通用型查找类
*/
@SuppressWarnings("unused")
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class BaseEm<T> {
/**
* 通过entityManager对象构建通用型查找函数.<br/>
* @param sql SQL查询语句
* @param queryParams 需替换的参数K-V
* @param clazz 映射的结果类型
* @param paramTypes 返回的各个字段类型
* @return 查找的结果列表
*/
public static<T> List<T> query(@Nonnull String sql, @Nullable Map<String, Object> queryParams,
@Nonnull Class<T> clazz, @Nonnull Class<?>... paramTypes) {
EntityManager em = BeanCreater.getBean(EntityManager.class);
assert em != null;
NativeQuery query = em.unwrap(Session.class).createNativeQuery(sql);
if (Objects.nonNull(queryParams) && queryParams.size() > 0) {
for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
query.setParameter(entry.getKey(), entry.getValue());
}
}
try {
Constructor<T> constructor = clazz.getConstructor(paramTypes);
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
String[] params = discoverer.getParameterNames(constructor);
assert params != null;
for (int i = 0; i < params.length; i++) {
Type hibernateType = java2Hibernate(paramTypes[i]);
query.addScalar(params[i], hibernateType);
}
query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(clazz));
return query.getResultList();
} catch (NoSuchMethodException e) {
throw new CustomException("没有匹配paramTypes的构造器: " + e.getMessage());
} finally {
em.close();
}
}
/**
* 将java类型转换成hibernate类型.<br/>
* @param javaClass java类型
* @return hibernate类型
*/
private static Type java2Hibernate(Class<?> javaClass) {
Map<Class, Type> map = new HashMap<>();
map.put(Boolean.class, StandardBasicTypes.BOOLEAN);
map.put(Byte.class, StandardBasicTypes.BYTE);
map.put(Short.class, StandardBasicTypes.SHORT);
map.put(Integer.class, StandardBasicTypes.INTEGER);
map.put(Long.class, StandardBasicTypes.LONG);
map.put(Float.class, StandardBasicTypes.FLOAT);
map.put(Double.class, StandardBasicTypes.DOUBLE);
map.put(BigInteger.class, StandardBasicTypes.BIG_INTEGER);
map.put(BigDecimal.class, StandardBasicTypes.BIG_DECIMAL);
map.put(Character.class, StandardBasicTypes.CHARACTER);
map.put(String.class, StandardBasicTypes.STRING);
map.put(Date.class, StandardBasicTypes.DATE);
map.put(Time.class, StandardBasicTypes.TIME);
map.put(Timestamp.class, StandardBasicTypes.TIMESTAMP);
map.put(Calendar.class, StandardBasicTypes.CALENDAR);
map.put(TimeZone.class, StandardBasicTypes.TIMEZONE);
map.put(LocalDate.class, LocalDateType.INSTANCE);
map.put(LocalTime.class, LocalTimeType.INSTANCE);
map.put(LocalDateTime.class, LocalDateTimeType.INSTANCE);
map.put(Locale.class, StandardBasicTypes.LOCALE);
map.put(Currency.class, StandardBasicTypes.CURRENCY);
return map.getOrDefault(javaClass, StandardBasicTypes.SERIALIZABLE);
}
}
调用示例:
仅供参考,全文完!