使用SPRING DATA JPA在保存/更新期间刷新实体

时间:2017-11-07 17:43:55

标签: spring hibernate jpa spring-data-jpa

我在Spring Boot中使用Spring Data JPA。

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

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

企业实体:

@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(组织)

{
    "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(),这将是性能问题。 这是保存/更新后刷新实体的唯一方法吗?或者我们可以通过添加任何配置等来避免这种情况。请建议。

感谢。

2 个答案:

答案 0 :(得分:0)

您在哪里创建&#34;组织&#34;宾语?。如果你在addOrganization()方法中创建或检索然后保存,你应该没问题。作为最佳实践,除非您使用OpenSessionInViewFilter将域传递给控制器​​并进行查看,否则服务层应该处理Domain对象而不是控制器。

答案 1 :(得分:0)

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

organizationRepository.save(organization);

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

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

编辑:

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

相关问题