这个问题类似于this one,但我的问题特别针对Spring Boot的原生CrudRepository和JpaRepository,它们似乎没有refresh()方法。我正在保存一个包含现有子对象的ID的新对象。应用程序是RESTful,插入的数据是来自客户端的JSON。正确插入新记录,但返回值中的子对象仍仅包含ID。 Spring Boot等效于refresh()吗?我是否需要创建可访问EntityManager的自定义存储库?
我应该在插入后使用findOne()来解决问题。子对象仍然不完整。但是,当我在单独的REST调用中选择插入的记录时,该对象与所有子对象一起完成。
代码如下。正如您所看到的,存储库和服务方法非常简单,我没有看到该做什么。刷新看起来像Spring Boot应该自动处理的东西。
注意:SO注释表单正在从CrudRepository中删除参数 返回类型。
@Entity
@JsonSerialize(using = VolumeSerializer.class)
public class Volume implements Protectable {
public static final int ATTACHED_STATE = 1;
public static final int DETACHED_STATE = 0;
public static final int SUSPENDED_STATE = -1;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
@OneToOne
private VolumeType type;
private int size;
@OneToOne
private UserGroup userGroup;
@OneToOne
private Region region;
@OneToOne
private State state;
@OneToOne
private Status status;
@OneToOne
private Alarm alarmStatus;
private long createdDate;
@Column(columnDefinition = "bigint default 0")
private long lastModifiedDate = 0;
@Column(columnDefinition = "tinyint default 0")
private boolean monitoringEnabled = false;
@Column(columnDefinition = "tinyint default 0")
private boolean encrypted = false;
@OneToOne
private Snapshot snapshot;
@ManyToOne
private Instance instance;
/*
after this there are constructors, a long list of getters for the properties above
a static Builder class and @PrePersist and @PreUpdate methods
*/
...
/**
* For accessing Volume information
*/
public interface VolumeRepository extends CrudRepository {
List findByUserGroupId(long groupId);
}
@Transactional
public Iterable save(List volumes) {
return this.repository.save(volumes);
}
这是一个@RestController。
@RequestMapping(value="/volumes", method=RequestMethod.POST)
public Iterable create(@RequestBody List volumes) {
return this.service.save(volumes);
}
(ddl-auto设置用于开发)
# Datasource configuration
spring.datasource.url=****
spring.datasource.username=****
spring.datasource.password=****
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.time-between-eviction-runs-millis=34000
spring.datasource.min-evictable-idle-time-millis=55000
spring.datasource.min-idle=0
# Hibernate settings
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
JSON字符串显示客户端所期望的内容 能够发送到服务。 UserGroup对象仅包含 从客户端发送的ID,但它应该是完整的UserGroup 宾语。其他子对象也是如此。
@Test
public void createVolume() throws Exception {
String json = "[{" +
"\"name\": \"Test Volume\", " +
"\"size\": 24, " +
"\"monitoringEnabled\": true, " +
"\"encrypted\": true, " +
"\"state\": { \"id\": 1 }, " +
"\"userGroup\": { \"id\": 1 }, " +
"\"region\": { \"id\": 1 }, " +
"\"type\": { \"id\": 1 }" +
"}]";
mvc.perform(MockMvcRequestBuilders.post("/volumes")
.principal(token)
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].id", is(4)))
.andExpect(jsonPath("$[0].name", is("Test Volume")))
.andExpect(jsonPath("$[0].size", is(24)))
.andExpect(jsonPath("$[0].userGroup.id", is(1)))
.andExpect(jsonPath("$[0].userGroup.name", is("myGroup")))
.andExpect(jsonPath("$[0].userGroup.users", isEmptyOrNullString()))
.andExpect(jsonPath("$[0].type.id", is(1)))
.andExpect(jsonPath("$[0].type.value", is("SSD")))
.andExpect(jsonPath("$[0].region.id", is(1)))
.andExpect(jsonPath("$[0].region.value", is("us-west")))
.andExpect(jsonPath("$[0].state.id", is(1)))
.andExpect(jsonPath("$[0].state.value", is("on")))
.andExpect(jsonPath("$[0].status", isEmptyOrNullString()))
//.andExpect(jsonPath("$.createdDate", is(1425240151000L)))
.andExpect(jsonPath("$[0].monitoringEnabled", is(true)))
.andExpect(jsonPath("$[0].encrypted", is(true)));
}
答案 0 :(得分:2)
在与同事协商后,我将EntityManager注入上面的VolumeService并在卷上调用了刷新。
@PersistenceContext
private EntityManager entityManager;
...
@Transactional
public Iterable save(List volumes) {
Iterable result = this.repository.save(volumes);
for (Volume volume : result){
entityManager.refresh(volume);
}
return result;
}
请注意,虽然我更喜欢这个选项,但我的同事建议获取子对象,将它们添加到新卷,然后保存卷,这显然有效。但是,我不想这样做。