【问题标题】:entity refresh during save/update using SPRING DATA JPA使用 SPRING DATA JPA 在保存/更新期间刷新实体
【发布时间】:2018-04-20 05:29:04
【问题描述】:

我在 Spring Boot 中使用 Spring Data JPA。

使用 Spring Data Jpa Repository 将实体保存到数据库后,我没有得到整个实体。即,仅获取我传递给 save() 的值。

所以,我检查了 google/SO,然后添加了 entityManager.refresh(organization)。现在我也得到了整个实体和映射的实体。

企业实体:

@Entity
@Table(name = "enterprise")
public class Enterprise extends BaseEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "enterprise_id")
    private Long enterpriseId;
    @Column(name = "enterprise_external_name", length = 150, unique = true)
    @NotNull
    private String enterpriseExternalName;
    @Column(name = "enterprise_internal_name", length = 150, unique = true)
    @NotNull
    private String enterpriseInternalName;
    @OneToMany(mappedBy = "enterprise")
    @JsonIgnoreProperties(allowSetters = true, value = { "enterprise" })
    private Set<Organization> organizations;
    //getter and setters
}

组织实体:

@Entity
@Table(name = "organization")
public class Organization extends BaseEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "organization_id")
    private Long organizationId;
    @Column(name = "organization_name", length = 150, unique = true)
    @NotBlank(message = "OrganizationName can't be empty !")
    private String organizationName;
    @ManyToOne
    @JoinTable(name = "enterprise_organization", joinColumns = {
            @JoinColumn(name = "organization_id") }, inverseJoinColumns = { @JoinColumn(name = "enterprise_id") })
    @JsonIgnoreProperties(allowSetters = true, value = { "organizations" })
    private Enterprise enterprise;
    //getters and setters
}

控制器类:

@PostMapping
public ResponseEntity<ValidationResponse> addOrganization(@Valid @RequestBody Organization organization)
{
    ValidationResponse response = new ValidationResponse();
    response.setMessage(organizationService.addOrganization(organization));

    return new ResponseEntity<ValidationResponse>(response, HttpStatus.CREATED);
}

服务类:

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class OrganizationServiceImpl implements OrganizationService {
    @PersistenceContext
    private EntityManager entityManager;
    @Autowired
    private OrganizationRepository organizationRepository;      
    public Organization addOrganization(Organization organization) {
        organization.setCreatedDate(Calendar.getInstance());
        organizationRepository.save(organization);
        entityManager.refresh(organization);
        return organization;
    }
}

存储库:

@Repository
public interface OrganizationRepository extends JpaRepository<Organization, Long> {
}

请求正文:

{
    "organizationName":"org5",
    "enterprise":{
        "enterpriseId":2
    }
}

响应如果我不包含 entityManager.refresh(organization):

{
    "success": true,
    "message": {
        "createdBy": 0,
        "updatedBy": 0,
        "createdDate": 1510140158654,
        "updatedDate": null,
        "organizationId": 14,
        "organizationName": "org5",
        "enterprise": {
            "createdBy": 0,
            "updatedBy": 0,
            "createdDate": null,
            "updatedDate": null,
            "enterpriseId": 2,            
            "enterpriseName": null,
            "active": true
        },
        "active": true
    },
    "errors": null
}

但我发现的问题是,它再次访问数据库并选择数据。如果我有更多映射并且在每个服务类方法中我需要添加 entityManager.refresh(),这将是一个性能问题。 这是保存/更新后刷新实体的唯一方法吗?或者我们可以通过添加任何配置等来避免这种情况吗?请提出建议。

谢谢。

【问题讨论】:

    标签: spring hibernate jpa spring-data-jpa


    【解决方案1】:

    我希望您的问题出在您的服务中。

    organizationRepository.save(organization);
    

    返回 save 方法的返回值,而不是返回参数对象。

    public Organization addOrganization(Organization organization) {
        organization.setCreatedDate(Calendar.getInstance());
        return organizationRepository.save(organization);;
    }
    

    编辑:

    重读问题后,我的回答完全没用。您可能必须将整个实体提供给 save 方法,或者如果您想坚持更新单个字段,请从存储库中获取它并在实体上设置字段。无需保存,因为后面的事务性写入将负责持久化更改。

    【讨论】:

    • @c-weber 你的意思是说,我需要使用从 save() 返回的 Id 获取整个实体?
    • 我将编辑我的答案以更清楚地说明我的意思。 save 方法不仅返回 ID,它还返回整个实体。
    • @c-weber 我已经尝试过了,但没有成功。 save() 的组织和值返回都是相同的。 save() 只是更新 ID 字段,仅此而已。
    • @c-weber 我已经用请求和响应更新了这个问题。请看一看。
    • 哦,您想更新现有组织。阅读您的问题时,我应该更加小心。那么这是一个不同的故事。据我所知,您不能只提供实体的几个字段来保存方法。在没有设置 ID 的情况下更是如此。在这种情况下,它将把它视为一个新组织并进行插入,而不是更新。我迷失了为什么刷新甚至可以工作。能否提供机构实体的代码?
    【解决方案2】:

    您在哪里创建“组织”对象?如果你在 addOrganization() 方法中创建或检索然后保存,你应该没问题。作为最佳实践,服务层应该处理域对象而不是控制器,除非您使用 OpenSessionInViewFilter 将域传递给控制器​​和视图。

    【讨论】:

    • 我通过添加控制器类更新了我的问题。请检查。仅供参考,我们只实现了 REST API。
    猜你喜欢
    • 2018-01-11
    • 1970-01-01
    • 2013-05-09
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多