【问题标题】:Is there a way to get a 'refreshed' saved entity when saving with JPA in Spring boot?在 Spring Boot 中使用 JPA 保存时,有没有办法获得“刷新”的保存实体?
【发布时间】:2020-09-03 02:45:44
【问题描述】:

首先,我不确定这是缓存请求还是不填充字段。

我有一个名为CmsRegions 的实体,其中包含以下内容:

public class CmsRegions extends Model implements Serializable {
       
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "name")
    private String name;
    
    @Lob
    @Size(max = 65535)
    @Column(name = "description")
    private String description;
    
    @Size(max = 2)
    @Column(name = "lang")
    private String lang;
    
    @Size(max = 2)
    @Column(name = "locale")
    private String locale;
    
    @Basic(optional = false)
    @NotNull
    @Column(name = "is_active")
    private short isActive;
    
    @Column(name = "parent_id")
    private Integer parentId;
        
    @Basic(optional = false)
    @Column(name = "created", insertable = false, updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;
    
    @Basic(optional = false)
    @Column(name = "modified", insertable = false, updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date modified;


    ...getters and setters etc...
}

我有基本的存储库调用来检索实体:

@NoRepositoryBean
public interface BaseCmsRepository<T extends Serializable> extends JpaRepository<T, Long> {
    
    @Query("SELECT a FROM #{#entityName} a WHERE a.id = :id")
    List<T> getById(
            @Param("id") Integer id
    );
    

当我保存实体时,它会保存到数据库中,如下表:

CREATE TABLE `cms_regions` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `description` text,
  `lang` char(2) DEFAULT NULL,
  `locale` char(2) DEFAULT NULL,
  `is_active` tinyint unsigned NOT NULL DEFAULT '0',
  `parent_id` int unsigned DEFAULT NULL,
  `created` datetime DEFAULT CURRENT_TIMESTAMP,
  `modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8;

createdmodified 字段按预期设置,但我从保存操作中获得的结果实体具有创建和修改日期的 NULL 值。

我运行了一个测试 - 我的最后一个插入 ID 是 31,所以我将以下代码添加到我的控制器:

    cmsService.saveRegion(region); // save entity

    CmsRegions  testreg1 = cmsService.getRegion(1);
    CmsRegions  testreg2 = cmsService.getRegion(region.getId());
    CmsRegions  testreg3 = cmsService.getRegion(30);
    CmsRegions  testreg4 = cmsService.getRegion(32);  // currently saved entity new ID (32)

执行此操作时 - testreg1 将创建和修改的日期包含为希望的 Date 对象。 testreg2 包含空值(此时 region.getId() = 32)。 testreg3 包含创建和修改的日期对象。

最终值 testreg4 也是 NULL。关键是,下次我运行它时,testreg4 中有 createdmodified 的值。但是下一次迭代,testreg2 中的 (33) 再次为 NULL。

我不知道这是缓存问题还是什么。似乎如果我尝试在调用完成之前提取数据库值 - 即使数据现在在数据库中(通过断点确认) - 结果字段始终为空。下一次运行,它们被填充。

为什么?我需要做什么才能获得这些值?

【问题讨论】:

    标签: java mysql spring spring-boot jpa


    【解决方案1】:

    当在任何类似接口上使用JpaRepository#save 或此方法保存时,将返回数据库中的实体。你可以使用它。最常用于填充生成的 id:

    assertNull(entity.getId());
    entity = entityRepository.save(entity);
    assertNotNull(entity.getId());
    

    当其他进程正在更改数据并且没有刷新持久性上下文时,情况会稍微复杂一些。那时将需要另一个查询。你可以通过使用EntityManager#refresh 并传递你想从数据库中“重新获取”的实体来解决这个问题。目前我不知道spring-data-jpa中是否存在该机制。

    【讨论】:

    • 我确实尝试使用 em.refresh,但即使是这种方法也在对数据库进行完整的新查询。为什么历史记录有效,而当前记录无效?
    • @BarryChapman 您可以使用保存时返回的实体,当不可能或有其他更改时,需要再次查询。查看我的编辑。
    • 我要添加一个自定义repo来扩展和使用刷新方法,给我几分钟把它放进去
    猜你喜欢
    • 1970-01-01
    • 2018-01-11
    • 2018-04-20
    • 2013-05-09
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    相关资源
    最近更新 更多