Hibernate JPA自定义通用DAO,自定义SQL,返回自定义对象。没有强关联实体基类。

基于Hibernate JPA,使用EntityManager实现

全部serviceImpl服务都继承通用服务类。避免频繁创建实体类。通用一个dao层。使用手搓SQL查询(sql注入使用其他方式解决)

支持返回:List<Map>、List<T>、Integer、String、<T>、Map

支持方法:save、delete、update、findOne、executeBySQL、batchSave、batchUpdate、getListBySQL、getNumBySQL、getStringBySQL

1、SQL结果转换类
import lombok.extern.slf4j.Slf4j;
import org.hibernate.transform.AliasToBeanResultTransformer;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * sql结果转换类,实体里驼峰命名法 与数据库里下划线命名 自动匹配
 */
@Slf4j
public class SqlResultTransformer extends AliasToBeanResultTransformer {

    private Class resultClass;
    public SqlResultTransformer(Class resultClass) {
        super(resultClass);
        this.resultClass = resultClass;
    }

    public Object transformTuple(Object[] tuple, String[] aliases) {
        Object obj = null;
        try {
            obj = resultClass.newInstance();
        } catch (InstantiationException e1) {
            e1.printStackTrace();
        } catch (IllegalAccessException e1) {
            e1.printStackTrace();
        }
        Method[] methods = resultClass.getMethods();// 返回这个类里面方法的集合
        for(int k=0;k<aliases.length;k++){
            String aliase=aliases[k];
            // cdd 把字段名中所有的下杠去除
            aliase = aliase.replaceAll("_", "").toLowerCase();
            char[] ch = aliase.toCharArray();
            ch[0] = Character.toUpperCase(ch[0]);
            String s = new String(ch);
            String[] names = new String[] { ("set" + s).intern(),
                    ("get" + s).intern(), ("is" + s).intern(),
                    ("read" + s).intern() };
            Method setter = null;
            Method getter = null;
            int length = methods.length;
            for (int i = 0; i < length; ++i) {
                Method method = methods[i];
                /**
                 * 检查该方法是否为公共方法,如果非公共方法就继续
                 */
                if (!Modifier.isPublic(method.getModifiers()))
                    continue;
                String methodName = method.getName();

                for (String name : names) {
                    if (name.toLowerCase().equals(methodName.toLowerCase())) {
                        if (name.startsWith("set") || name.startsWith("read"))
                            setter = method;
                        else if (name.startsWith("get") || name.startsWith("is"))
                            getter = method;

                    }
                }
            }
            if(getter!=null){
                Object[] param = buildParam(getter.getReturnType().getName(), tuple[k]);
                try {
                    setter.invoke(obj, param);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return obj;
    }

    private final static Object[] buildParam(String paramType, Object value) {
        Object[] param = new Object[1];
        if (paramType.equalsIgnoreCase("java.lang.String")) {
            param[0] = (String)(value);
        } else if (paramType.equalsIgnoreCase("int")
                || paramType.equalsIgnoreCase("java.lang.Integer")) {
            try {
                param[0] = (Integer)(value);
            } catch (Exception e) {
                param[0] = Integer.valueOf(value.toString());
            }
        } else if (paramType.equalsIgnoreCase("long")|| paramType.equalsIgnoreCase("java.lang.Long")) {
            param[0] = (Long)(value);
        } else if (paramType.equalsIgnoreCase("double")|| paramType.equalsIgnoreCase("java.lang.Double")) {
            try {
                param[0] = (Double)(value);
            } catch (Exception e) {
                param[0] = Double.valueOf(value.toString());
            }
        } else if (paramType.equalsIgnoreCase("float")|| paramType.equalsIgnoreCase("java.lang.Float")) {
            param[0] = (Float)(value);
        } else if (paramType.equalsIgnoreCase("char")
                || paramType.equalsIgnoreCase("Character")) {
            param[0] = (char)(value);
        } else if (paramType.equalsIgnoreCase("java.util.Date")){
            param[0] = (java.util.Date)(value);
        }
        else if (paramType.equalsIgnoreCase("java.sql.Timestamp")){
            param[0] = (java.sql.Timestamp)(value);
        }else if (paramType.equalsIgnoreCase("java.math.BigInteger")){
            param[0] = (java.math.BigInteger)(value);
        }else if (paramType.equalsIgnoreCase("java.math.BigDecimal")){
            param[0] = (java.math.BigDecimal)value;
        }
        return param;
    }

}
2、Dao
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component  //标记为组件,spring启动时要将该类扫描进容器
public class BaseDaoImp {

    @PersistenceContext //注入的是实体管理器,执行持久化操作
    private EntityManager entityManager;


    public void save(Object obj) {
        entityManager.persist(obj);
    }

    public <T, ID extends Serializable> void delete(Class<T> cls, ID id) {
        T t = entityManager.find(cls, id);
        entityManager.remove(t);
    }

    public <T> T update(T obj) {
        return entityManager.merge(obj);
    }

    public <T, ID extends Serializable> T findOne(Class<T> cls, ID id) {
        return entityManager.find(cls, id);
    }

    @Transactional(readOnly = true)
    public Object getObjectBySQL(final String sql, final ResultTransformer rt) {
        Object obj = null;
        try {
            Query query = entityManager.createNativeQuery(sql);
            if (rt != null) {
                query.unwrap(NativeQueryImpl.class).setResultTransformer(rt);
            }
            List list = query.getResultList();
            if (null != list && list.size() > 0) {
                obj = list.get(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

    @Transactional(readOnly = true)
    public List getListBySQL(String sql, ResultTransformer rt) {
        Query query = entityManager.createNativeQuery(sql);
        if (rt != null) {
            query.unwrap(NativeQueryImpl.class).setResultTransformer(rt);
        }
        List list = query.getResultList();
        return list;
    }

    @Transactional(readOnly = true)
    public List<Map> getListBySQL(String sql) {
        Query query = entityManager.createNativeQuery(sql);
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map> list = query.getResultList();
        return list;
    }


    public List findBySQL(String sql) {
        Query query = entityManager.createNativeQuery(sql);
        List list = query.getResultList();
        return list;
    }

    public Integer getNumBySQL(String sql) {
        Integer num = 0;
        Query query = entityManager.createNativeQuery(sql);
        Object obj = query.getSingleResult();
        num = Integer.valueOf(obj.toString());
        return num;
    }

    public String getStringBySQL(String sql) {
        Query query = entityManager.createNativeQuery(sql);
        Object obj = query.getSingleResult();
        return obj.toString();
    }

    public Integer executeBySQL(String sql) {
        Query query = entityManager.createNativeQuery(sql);
        final int i = query.executeUpdate();
        return i;
    }

    public void batchSave(List list) {
        for (int i = 0; i < 10000 && i < list.size(); i++) {
            entityManager.persist(list.get(i));
            if (i % 1000 == 0) {
                entityManager.flush();
                entityManager.clear();
            }
        }
    }

    public void batchUpdate(List list) {
        for (int i = 0; i < list.size(); i++) {
            entityManager.merge(list.get(i));
            if (i % 100 == 0) {
                entityManager.flush();
                entityManager.clear();
            }
        }
    }

    /**
     * 新增实体,数据库主键自增,同时实体主键为空
     *
     * @param obj
     */
    public void insert(Object obj) {
        entityManager.persist(obj);
    }

    @Transactional(readOnly = true)
    public List<Map> getBySQL(String sql) {
        Query nativeQuery = entityManager.createNativeQuery(sql);
        nativeQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List resultList = nativeQuery.getResultList();
        return resultList;
    }

    public Map uniqueResult(String sql) {

        Map re = new HashMap();
        List<Map> listMap = getBySQL(sql);
        if (null != listMap && listMap.size() > 0) {
            re = listMap.get(0);
        }
        return re;
    }
4、Service

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;

public class BaseServiceImp<T extends Object, ID extends Serializable> {

    @Autowired
    private BaseDaoImp baseDaoImp;


    @Transactional
    public void save(T t) {
        baseDaoImp.save(t);
    }

    @Transactional
    public void delete(ID id) {
        Class<T> tClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        baseDaoImp.delete(tClass, id);
    }

    @Transactional
    public void deleteByIds(String ids) {
        String strIdArr[] = ids.split(",");
        for (String idStr : strIdArr) {
            ID id = (ID) idStr;
            delete(id);
        }
    }

    @Transactional
    public T update(T t) {
        return baseDaoImp.update(t);
    }

    @Transactional
    public void batchSave(List list) {
        baseDaoImp.batchSave(list);
    }

    @Transactional
    public void batchUpdate(List list) {
        baseDaoImp.batchUpdate(list);
    }

    @Transactional
    public Integer executeBySQL(String sql) {
        return baseDaoImp.executeBySQL(sql);
    }

    @Transactional
    public T findOne(ID id) {
        Class<T> tClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return baseDaoImp.findOne(tClass, id);
    }

    @Transactional
    public void insert(Object obj) {
        baseDaoImp.insert(obj);
    }

    /**
     * 建议单表查询时候使用; 复杂的sql语句不要用这个方法,比如带Group By分组的语句,统计count会出问题
     *
     * @param querySql
     * @param cls
     * @return
     */
    public QueryResultVO queryBySql(String querySql, Class cls) {
        int lastIndex = querySql.length();
        if (querySql.toLowerCase().indexOf("order by") != -1) {
            lastIndex = querySql.toLowerCase().indexOf("order by");
        }
        String countSql = "select count(*) " + querySql.substring(querySql.toLowerCase().indexOf("from"), lastIndex);
        QueryResultVO queryResultVO = new QueryResultVO();
        List list = baseDaoImp.getListBySQL(querySql, new SqlResultTransformer(cls));
        int count = baseDaoImp.getNumBySQL(countSql);
        queryResultVO.setResultList(list);
        queryResultVO.setTotalRecords(count);
        return queryResultVO;
    }

    public List getListBySQL(String sql, Class cls) {
        return baseDaoImp.getListBySQL(sql, new SqlResultTransformer(cls));
    }

    public List<Map> getListBySQL(String sql) {
        return baseDaoImp.getListBySQL(sql);
    }

    public Integer getNumBySQL(String sql) {
        return baseDaoImp.getNumBySQL(sql);
    }

    public Object getObjectBySQL(String sql, Class cls) {
        return baseDaoImp.getObjectBySQL(sql, new SqlResultTransformer(cls));
    }

    public <E> E getObjectBySQL(String sql, E e) {
        return (E) baseDaoImp.getObjectBySQL(sql, new SqlResultTransformer(e.getClass()));
    }

5、使用

@Service
public class ServiceImpl extends BaseServiceImp implements Service 

    public List<TableDTO> getTableDTOList(VO vo) {
        String sql = "SELECT * FROM table ";
        sql += this.getWhereSql(vo);
        sql += "GROUP BY field";
        List<TableDTO> list = this.getListBySQL(sql, TableDTO.class);
        return list ;
    }
}


@Service
public class ServiceImpl extends BaseServiceImp<MO, Integer> {
	
    @Transactional
	public void addMo(MO mo){
		this.save(mo);
	}
}


import lombok.Data;
import javax.persistence.*;

@Data
@Entity
@Table(name = "table_name")
public class MO {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JPA 中,你可以使用以下几种方式来返回自定义对象: 1. 使用构造函数表达式:你可以在查询中使用构造函数表达式来创建自定义对象。假设你有一个名为 `CustomObject` 的类,它有一个带有参数的构造函数,你可以在查询中使用这个构造函数来返回自定义对象。例如: ```java String jpql = "SELECT NEW com.example.CustomObject(c.name, c.age) FROM Customer c"; TypedQuery<CustomObject> query = entityManager.createQuery(jpql, CustomObject.class); List<CustomObject> resultList = query.getResultList(); ``` 2. 使用 `@SqlResultSetMapping`:你可以在实体类中使用 `@SqlResultSetMapping` 注解来定义结果映射。首先,在实体类中定义一个构造函数,然后在 `@SqlResultSetMapping` 注解中指定该构造函数的参数映射。例如: ```java @SqlResultSetMapping( name = "CustomObjectMapping", classes = @ConstructorResult( targetClass = CustomObject.class, columns = { @ColumnResult(name = "name", type = String.class), @ColumnResult(name = "age", type = Integer.class) } ) ) @Entity public class Customer { // ... } ``` 然后,在查询时使用 `@SqlResultSetMapping` 注解的名称来指定结果映射。例如: ```java String jpql = "SELECT c.name, c.age FROM Customer c"; TypedQuery<CustomObject> query = entityManager.createNativeQuery(jpql, "CustomObjectMapping"); List<CustomObject> resultList = query.getResultList(); ``` 3. 使用投影(Projection):你可以使用投影的方式来选择实体类的部分属性,并将它们映射到自定义对象中。例如: ```java String jpql = "SELECT c.name, c.age FROM Customer c"; TypedQuery<Object[]> query = entityManager.createQuery(jpql, Object[].class); List<Object[]> resultList = query.getResultList(); List<CustomObject> customObjects = resultList.stream() .map(objArr -> new CustomObject((String) objArr[0], (Integer) objArr[1])) .collect(Collectors.toList()); ``` 这些是几种常见的在 JPA返回自定义对象的方式。你可以根据具体的业务需求选择最适合你的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值