在Spring Boot中保存Map属性时出现TransientObjectException

如何解决在Spring Boot中保存Map属性时出现TransientObjectException

查找具有Map属性的持久对象时出现以下错误:

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: [package].MapKey; nested exception is java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: [package].MapKey

我发现大多数说明都是关于添加CascadeType.ALL的。

仅当我执行自定义查询时才显示错误,而不是使用findById方法:

EntityWithMap saved = service.save(entity);
    
assertEquals(entity.getMap(),service.findById(saved.getId()).get().getMap()); //No error

assertEquals(entity.getMap(),service.findByName("test entity").get(0).getMap()); //InvalidDataAccessApiUsageException

EntityWithMap:

@Entity
public class EntityWithMap {

    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
    @JoinTable(name = "mapping_mapkey_mapvalue",joinColumns = {@JoinColumn(name = "value_id",referencedColumnName = "id")},inverseJoinColumns = {@JoinColumn(name = "entity_id",referencedColumnName = "id")})
    @MapKeyJoinColumn(name = "key_id",referencedColumnName = "id")
    private Map<MapKey,MapValue> map = new HashMap<>();

    private String name;
    
    public EntityWithMap(String name) {
        this.name = name;
    }

    public Map<MapKey,MapValue> getMap() {
        return map;
    }
    
    public Long getId() {
        return id;
    }
    
    public void addToMap(MapKey key,MapValue value) {
        map.put(key,value);
    }
    
}

MapKey:

@Entity
public class MapKey {

    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
}

MapValue:

@Entity
public class MapValue {

    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
}

测试类:

@DataJpaTest
@Import(EntityWithMapService.class)
public class PersistMappingTest {

    @Autowired private EntityWithMapService service;
    
    @Test
    public void testPersistence() {
        
        EntityWithMap entity = new EntityWithMap("test entity");
        entity.addToMap(new MapKey(),new MapValue());
        entity.addToMap(new MapKey(),new MapValue());

        EntityWithMap saved = service.save(entity);
        
        assertEquals(entity.getMap(),service.findById(saved.getId()).get().getMap()); //No error

        assertEquals(entity.getMap(),service.findByName("test entity").get(0).getMap()); //InvalidDataAccessApiUsageException
    }
}

EntityWithMapService:

@Service
public class EntityWithMapService {

    private EntityWithMapRepository repository;

    public EntityWithMapService(EntityWithMapRepository repository) {
        this.repository = repository;
    }

    public EntityWithMap save(EntityWithMap entity) {
        return repository.save(entity);
    }

    public Optional<EntityWithMap> findById(Long id) {
        return repository.findById(id);
    }
    
    public List<EntityWithMap> findByName(String name) {
        return repository.findByName(name);
    }
    
}

EntityWithMapRepository:

@Repository
public interface EntityWithMapRepository extends JpaRepository<EntityWithMap,Long> {
    
    @Query("FROM EntityWithMap e WHERE e.name = :name")
    public List<EntityWithMap> findByName(@Param("name") String name);

}

解决方法

在您的示例中有几处地方似乎不对。

  1. 您的测试Node* &rightNode = getNodeToBeReplaced(); //returns y Node* assignNode = rightNode->parentNode; //returns assign node with x = y auto &parentChild = std::find(assignNode->childNodes.begin(),assignNode->childNodes.end(),rightNode); Var* replacementNode = new Var("z"); *replacementNode->parentNode = *assignNode; **toBeReplacedParentChild = *replacementNode; 试图通过引用childNodesPersistMappingTest的实例来持久保存EntityWithMap的记录,而不先保持它们的持久性。您需要先保存MapKeyMapValue记录,然后才能将它们用作MapKey记录中的引用。这可能是您获得MapValue的主要原因。

示例(伪代码):

EntityWithMap

注意:如果有意不将TransientObjectExceptionMapKey mapKey1 = mapKeyService.save(new MapKey()); MapKey mapKey2 = mapKeyService.save(new MapKey()); MapKey mapKey3 = mapKeyService.save(new MapKey()); MapValue mapValue1 = mapValueService.save(new MapValue()); MapValue mapValue2 = mapValueService.save(new MapValue()); MapValue mapValue3 = mapValueService.save(new MapValue()); EntityWithMap entity = new EntityWithMap("test entity"); entity.addToMap(mapKey1,mapValue1); entity.addToMap(mapKey2,mapValue2); entity.addToMap(mapKey3,mapValue3); 映射保留在数据库中并且仅用于内存中,请尝试将MapKey批注添加到映射字段中在MapValue中。

  1. 您的@Transient实体根本没有引用EntityWithMap。如果MapValue不知道,MapKey怎么能成为MapKey的密钥。

示例(伪代码):

MapValue
  1. 您无需在实体MapValue中的地图声明中创建@Entity public class MapValue { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Long id; @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "mapkey_id") private MapKey mapKey; } 的新实例。 JPA应该为您做到这一点。这也可能是您得到例外的原因。

有关更多信息,请参见本文: https://www.baeldung.com/hibernate-persisting-maps

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-