在学习Springboot jpa构建通用Dao方法时出现org.hibernate.PersistentObjectException异常,但是数据已经成功的插入了数据库!就很不理解,百度了一大堆都是说数据插入不成功的!
实体类User如下:
@Entity
public class User implements Serializable{
@Id
@GeneratedValue
private long userId; //用户Id
@Column(nullable=false)
private String userName; //用户名
@Column(nullable=false)
private String realName; //真实姓名
@Column(nullable=false,length=11)
private long userPhone; //手机
@Email
@Column(nullable=false)
private String userEmail; //邮箱
@Column(nullable=false)
private String password; //密码
@Column(nullable=false)
private String userAddress; //地址
@Column(nullable=false)
@DateTimeFormat(style = "yyyy-MM-dd HH:mm:ss")
private Date birthdate; //出生日期
@Column(nullable=false)
@DateTimeFormat(style = "yyyy-MM-dd HH:mm:ss")
private Date registerdate; //注册时间
@Transient
private String provence;
@Transient
private String city;
@Transient
private String town;
@Transient
private String detail; 省略get、set方法
下面是我的通用BaseAppDAO接口:
package com.blog.XXY.repository;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
public interface BaseAppDAO<T,ID extends Serializable> {
/**
* 保存数据对象
* @param entity
* @return
*/
boolean save(T entity);
/**
* 根据id查询
* @param id
* @param t
* @return
*/
T findByid(T t,Long id);
/**
* 根据表名,字段,参数查询,拼接sql语句
* @param tablename 表名
* @param filed 字段名
* @param o 字段参数
* @return
*/
List<T> findBysql(String tablename,String filed,Object o);
Object findObjiectBysql(String tablename,String filed,Object o);
/**
* 多个字段的查询
* @param tablename 表名
* @param map 将你的字段传入map中
* @return
*/
List<T> findByMoreFiled(String tablename,LinkedHashMap<String,Object> map);
/**
* 多字段查询分页
* @param tablename 表名
* @param map 以map存储key,value
* @param start 第几页
* @param pageNumer 一个页面的条数
* @return
*/
List<T> findByMoreFiledpages(String tablename, LinkedHashMap<String,Object> map, int start, int pageNumer);
/**
* 一个字段的分页
* @param tablename 表名
* @param filed 字段名
* @param o 字段参数
* @param start 第几页
* @param pageNumer 一个页面多少条数据
* @return
*/
List<T> findpages(String tablename,String filed,Object o,int start,int pageNumer);
/**
* 根据表的id删除数据
* @param entity
*/
boolean delete(T entity);
/**
* 更新对象
* @param e
* @return
*/
boolean update(T e);
/**
* 根据传入的map遍历key,value拼接字符串,以id为条件更新
* @param tablename 表名
* @param map 传入参数放入map中
* @return
*/
Integer updateMoreFiled(String tablename,LinkedHashMap<String,Object> map);
/**
* 根据条件查询总条数返回object类型
* @param tablename 表名
* @param map 传入参数放入map中
* @return
*/
Object findCount(String tablename, LinkedHashMap<String,Object> map);
}
实现类BaseAppDAOimpl<T,ID extends Serializable> implements BaseAppDAO<T,ID>如下:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import org.springframework.stereotype.Repository;
import com.blog.XXY.repository.BaseAppDAO;
/**
* @author ChenX
* @create 2018-04-01 19:11
* @desc
**/
@Repository
public class BaseAppDAOimpl<T,ID extends Serializable> implements BaseAppDAO<T,ID> {
@PersistenceContext
private EntityManager entityManager;
@Transactional
@Override
public boolean save(T entity){
boolean flag=false;
try {
entityManager.persist(entity);
flag=true;
}catch (Exception e){
System.out.println("---------------保存出错---------------"+flag);
throw e;
}
return flag;
}
@Transactional
@Override
public Object findByid(Object o,Long id) {
return entityManager.find(o.getClass(),id);
}
@Transactional
@Override
public List<T> findBysql(String tablename, String filed, Object o ) {
String sql="from "+tablename+" u WHERE u."+filed+"=?";
System.out.println(sql+"--------sql语句-------------");
Query query=entityManager.createQuery(sql);
query.setParameter(1,o);
List<T> list= query.getResultList();
entityManager.close();
return list;
}
@Override
public Object findObjiectBysql(String tablename, String filed, Object o) {
String sql="from "+tablename+" u WHERE u."+filed+"=?";
System.out.println(sql+"--------sql语句-------------");
Query query=entityManager.createQuery(sql);
query.setParameter(1,o);
entityManager.close();
return query.getSingleResult();
}
@Transactional
@Override
public List<T> findByMoreFiled(String tablename,LinkedHashMap<String,Object> map) {
String sql="from "+tablename+" u WHERE ";
Set<String> set=null;
set=map.keySet();
List<String> list=new ArrayList<>(set);
List<Object> filedlist=new ArrayList<>();
for (String filed:list){
sql+="u."+filed+"=? and ";
filedlist.add(filed);
}
sql=sql.substring(0,sql.length()-4);
System.out.println(sql+"--------sql语句-------------");
Query query=entityManager.createQuery(sql);
for (int i=0;i<filedlist.size();i++){
query.setParameter(i+1,map.get(filedlist.get(i)));
}
List<T> listRe= query.getResultList();
entityManager.close();
return listRe;
}
@Transactional
@Override
public List<T> findByMoreFiledpages(String tablename,LinkedHashMap<String,Object> map,int start,int pageNumber) {
String sql="from "+tablename+" u WHERE ";
Set<String> set=null;
set=map.keySet();
List<String> list=new ArrayList<>(set);
List<Object> filedlist=new ArrayList<>();
for (String filed:list){
sql+="u."+filed+"=? and ";
filedlist.add(filed);
}
sql=sql.substring(0,sql.length()-4);
System.out.println(sql+"--------sql语句-------------");
Query query=entityManager.createQuery(sql);
for (int i=0;i<filedlist.size();i++){
query.setParameter(i+1,map.get(filedlist.get(i)));
}
query.setFirstResult((start-1)*pageNumber);
query.setMaxResults(pageNumber);
List<T> listRe= query.getResultList();
entityManager.close();
return listRe;
}
@Transactional
@Override
public List<T> findpages(String tablename, String filed, Object o, int start, int pageNumer) {
String sql="from "+tablename+" u WHERE u."+filed+"=?";
System.out.println(sql+"--------page--sql语句-------------");
List<T> list=new ArrayList<>();
try {
Query query=entityManager.createQuery(sql);
query.setParameter(1,o);
query.setFirstResult((start-1)*pageNumer);
query.setMaxResults(pageNumer);
list= query.getResultList();
entityManager.close();
}catch (Exception e){
System.out.println("------------分页错误---------------");
}
return list;
}
@Transactional
@Override
public boolean update(T entity) {
boolean flag = false;
try {
entityManager.merge(entity);
flag = true;
} catch (Exception e) {
System.out.println("---------------更新出错---------------");
}
return flag;
}
@Transactional
@Override
public Integer updateMoreFiled(String tablename, LinkedHashMap<String, Object> map) {
String sql="UPDATE "+tablename+" AS u SET ";
Set<String> set=null;
set=map.keySet();
List<String> list=new ArrayList<>(set);
for (int i=0;i<list.size()-1;i++){
if (map.get(list.get(i)).getClass().getTypeName()=="java.lang.String"){
System.out.println("-*****"+map.get(list.get(i))+"------------"+list.get(i));
sql+="u."+list.get(i)+"='"+map.get(list.get(i))+"' , ";
}else {
sql+="u."+list.get(i)+"="+map.get(list.get(i))+" , ";
}
}
sql=sql.substring(0,sql.length()-2);
sql+="where u.id=? ";
System.out.println(sql+"--------sql语句-------------");
int resurlt=0;
try {
Query query=entityManager.createQuery(sql);
query.setParameter(1,map.get("id"));
resurlt= query.executeUpdate();
}catch (Exception e){
System.out.println("更新出错-----------------------");
e.printStackTrace();
}
return resurlt;
}
@Transactional
@Override
public boolean delete(T entity) {
boolean flag=false;
try {
entityManager.remove(entityManager.merge(entity));
flag=true;
}catch (Exception e){
System.out.println("---------------删除出错---------------");
}
return flag;
}
@Override
public Object findCount(String tablename, LinkedHashMap<String, Object> map) {
String sql="select count(u) from "+tablename+" u WHERE ";
Set<String> set=null;
set=map.keySet();
List<String> list=new ArrayList<>(set);
List<Object> filedlist=new ArrayList<>();
for (String filed:list){
sql+="u."+filed+"=? and ";
filedlist.add(filed);
}
sql=sql.substring(0,sql.length()-4);
System.out.println(sql+"--------sql语句-------------");
Query query=entityManager.createQuery(sql);
for (int i=0;i<filedlist.size();i++){
query.setParameter(i+1,map.get(filedlist.get(i)));
}
return query.getSingleResult();
}
}
测试类如下:
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.blog.XXY.domain.User;
import com.blog.XXY.repository.BaseAppDAO;
@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTests {
@Autowired
private BaseAppDAO<User, Serializable> userDao;
@Test
public void contextLoads() {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
Date dayDateUtil;
try {
dayDateUtil = df.parse("20110413111100");
java.sql.Date dayDateSql = new java.sql.Date(dayDateUtil.getTime());
User u=new User();
// u.setUserId(110);
u.setUserName("你大爷一号");
u.setRealName("你大妈一号");
u.setPassword("123456");
u.setUserPhone(18325545614l);
u.setRegisterdate(dayDateSql);
u.setBirthdate(dayDateSql);
u.setCity("测试");
u.setProvence("湖北省");
u.setTown("嘎达乡");
u.setDetail("最牛逼村寨");
u.setUserAddress(u.getProvence()+u.getCity()+u.getTown()+u.getDetail());
u.setUserEmail("xxx@163.com");
boolean user = userDao.save(u);
if (user) {
System.out.println(user);
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
控制台打印异常如下:
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.blog.cxy.domain.User; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.blog.cxy.domain.User
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:280)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:507)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.blog.cxy.repository.impl.BaseAppDAOimpl$$EnhancerBySpringCGLIB$$fb5f0ca5.save(<generated>)
at com.blog.cxy.AppTests.contextLoads(AppTests.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.blog.cxy.domain.User
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:782)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:767)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:304)
at com.sun.proxy.$Proxy88.persist(Unknown Source)
at com.blog.cxy.repository.impl.BaseAppDAOimpl.save(BaseAppDAOimpl.java:33)
at com.blog.cxy.repository.impl.BaseAppDAOimpl$$FastClassBySpringCGLIB$$eb9ec0f5.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 38 more
下面是异常信息:
后来请教了一位大牛,才发现是boot版本与本地的JDK版本不对应!
Springboot 1.5版本对应JDK1.8以上(1.7没测过);
Springboot 2.0版本对应JDK1.9(低了就报这个错误);
解决办法:把JDK版本与Springboot版本对应!
1.5.x对应JDK1.8(亲测没毛病);
2.0.0对应JDK1.9.
大牛勿喷,互相交流!