Spring JPA实战反馈

一.定义实体类

 

1.对应的属性名字一定要小写,不然userName会被映射成user_name

2.不需要生成新的表配置上添加:#spring.jpa.hibernate.ddl-auto=update

3.要注意JPA Repository的一系列子类在继承的时候 如:CrudRepository<User, Integer>  User:是映射表的实体类,Integer是表的主键  

4.如果想接收非数据表映射结果集如:

@Query(value="select a.*,b.name from user a left join info b on a.id=b.uid where b.id in(: ids)",nativeQuery=true)

List<Object[]> getUserInfoByInfoID(@Param("ids") List<Long>ids)

要注意:结果集用Object[]接收 再将其转化为自己定义好的实体

转化方法:

List<Object[]> userInfoList=userRepository.getUserInfoByInfoID(ids);

List<UserInfoDTO> dialTestList=EntityUntil.castEntity(userInfoList,UserInfoDTO.class,newUserInfoDTO() );

package com.tencent.examples.util;

 

import org.apache.http.util.EntityUtils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

 

 

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

 

public class EntityUntil {

private static Logger logger = LoggerFactory.getLogger(EntityUtils.class);

 

/**

* 将数组数据转换为实体类

* 此处数组元素的顺序必须与实体类构造函数中的属性顺序一致

*

* @param list 数组对象集合

* @param clazz 实体类

* @param <T> 实体类

* @param model 实例化的实体类

* @return 实体类集合

*/

public static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz, Object model) {

List<T> returnList = new ArrayList<>();

if (list.isEmpty()) {

return returnList;

}

//获取每个数组集合的元素个数

Object[] co = list.get(0);

 

//获取当前实体类的属性名、属性值、属性类别

List<Map> attributeInfoList = getFiledsInfo(model);

//创建属性类别数组

Class[] c2 = new Class[attributeInfoList.size()];

//如果数组集合元素个数与实体类属性个数不一致则发生错误

if (attributeInfoList.size() != co.length) {

return returnList;

}

//确定构造方法

for (int i = 0; i < attributeInfoList.size(); i++) {

c2[i] = (Class) attributeInfoList.get(i).get("type");

}

try {

for (Object[] o : list) {

int a= o.length;

Constructor<T> constructor = clazz.getConstructor(c2);

returnList.add(constructor.newInstance(o));

}

} catch (Exception ex) {

logger.error("实体数据转化为实体类发生异常:异常信息:{}", ex.getMessage());

return returnList;

}

return returnList;

}

 

/**

* 根据属性名获取属性值

*

* @param fieldName 属性名

* @param modle 实体类

* @return 属性值

*/

private static Object getFieldValueByName(String fieldName, Object modle) {

try {

String firstLetter = fieldName.substring(0, 1).toUpperCase();

String getter = "get" + firstLetter + fieldName.substring(1);

Method method = modle.getClass().getMethod(getter, new Class[]{});

Object value = method.invoke(modle, new Object[]{});

return value;

} catch (Exception e) {

return null;

}

}

 

/**

* 获取属性类型(type),属性名(name),属性值(value)的map组成的list

*

* @param model 实体类

* @return list集合

*/

private static List<Map> getFiledsInfo(Object model) {

Field[] fields = model.getClass().getDeclaredFields();

List<Map> list = new ArrayList(fields.length);

Map infoMap = null;

for (int i = 0; i < fields.length; i++) {

infoMap = new HashMap(3);

infoMap.put("type", fields[i].getType());

infoMap.put("name", fields[i].getName());

infoMap.put("value", getFieldValueByName(fields[i].getName(), model));

list.add(infoMap);

}

return list;

}

 

}

二.报错

1.org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet;

SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet

这个问题说明:1.可能SQL语句有问题,2.可能接收结果的实体类有错,注意属性名小写 3.参数要一致

2.如果要修改数据库值,一定要加上@Transactional,可以加在Repository的方法上,可以加载ServiceImpl的方法上

3.新发现的问题,是在坑爹,数据库一定要命名规范!!!不要用大写,如果是词组要用_分割而不是驼峰式!!!比如:order_ext  不要写成orderExt!!!  因为在底层转换的时候,如果你实际上的表名是orderExt,会被转成order_ext,但实际你的库里根本没有order_ext,如果全小写orderext那更不可能找到了。这时候你根本用不了CrudRepository里面的的方法,只能老老实实的手动@Query(“insertXXX”)。

还有一个坑爹的地方,可能是我没找到方法,不能对象insert进去 ,只能拆成好几个参数挨个塞进去。有人有好的方法请告诉我~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值