#java #json #spring #jpa #jackson
#java #json #spring #jpa #джексон
Вопрос:
У меня есть файл json с объектом json в качестве значения свойства внутри:
{
"name": "name",
"json": {...}
}
Мне нужно автоматически получить его в RestController и использовать его как объект в JPA Hibernate.
Моя сущность:
ОБНОВИТЬ -> более определенный объект
@Entity
@Table(name = "collections")
public class Collection {
@Id
private String name;
@Column(name = "cache_limit")
private int limit;
@Column(name = "cache_algorithm")
private String algorithm;
@Transient
private JsonNode schema;
@JsonIgnore
@Column(name ="json_schema")
private String jsonSchema;
public Collection() {
}
public String getJsonSchema() {
return schema.toString();
}
public void setJsonSchema(String jsonSchema) {
ObjectMapper mapper = new ObjectMapper();
try {
schema = mapper.readTree(jsonSchema);
} catch (IOException e) {
throw new RuntimeException("Parsing error -> String to JsonNode");
}
}
..setters and getters for name limit algorithm schema..
}
Когда я использую, entityManager.persist(Collection)
у меня есть json_schema
столбец как NULL
Как я могу это решить? Возможно, проблема в setJsonSchema()
Обновить:
public String getJsonSchema() {
return jsonSchema;
}
public void setJsonSchema(JsonNode schema) {
this.jsonSchema = schema.toString();
}
Такие методы получения / установки не решают проблему
Комментарии:
1. Что вы подразумеваете под «поле json будет пустым».? Ваш контроллер выглядит так,
Cat getCat(int name){ return cats.getCatByName(name);}
и он возвращаетJSON
объект сname
иjson
свойство пусто?
Ответ №1:
Вы могли бы определить JsonNode json
свойство как @Transient
, чтобы JPA не пытался сохранить его в базе данных. Однако jackson должен уметь переводить его обратно и вперед в Json.
Затем вы можете закодировать getter / setter для JPA, чтобы переводить из JsonNode в строку назад и вперед. Вы определяете средство получения, getJsonString
которое переводится JsonNode json
в String
. Его можно сопоставить со столбцом таблицы, например ‘json_string’, затем вы определяете сеттер, в котором вы получаете String
из JPA, и анализируете его в JsonNode, который будет доступен для jackson.
Не забудьте добавить @JsonIgnore
в getJsonString
, чтобы Jackson не пытался перевести в json как jsonString.
@Entity
@Table(name = "cats")
public class Cat {
private Long id;
private String name;
@Transient
private JsonNode json;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name ="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setId(Long id) {
this.id = id;
}
// Getter and setter for name
@Transient
public JsonNode getJson() {
return json;
}
public void setJson(JsonNode json) {
this.json = json;
}
@Column(name ="jsonString")
public String getJsonString() {
return this.json.toString();
}
public void setJsonString(String jsonString) {
// parse from String to JsonNode object
ObjectMapper mapper = new ObjectMapper();
try {
this.json = mapper.readTree(jsonString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Комментарии:
1. Это немного странно, но json.asText() не работает. json.toString() работает
2. Когда я использую JPA, этот столбец @JsonIgnore равен нулю
3. Можете ли вы выполнить отладку и посмотреть, каково значение json в get / setJsonString?
4. get/setJsonString работают корректно. После использования EntityManager.persist (cat) у меня в базе данных NULL
5. Я могу удалить @Column(name =»json_string») — результат был бы тем же
Ответ №2:
Как объясняется в этой статье, вам не нужно создавать пользовательский тип гибернации вручную, поскольку вы можете просто получить его через Maven Central, используя следующую зависимость:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Для получения дополнительной информации ознакомьтесь с проектом с открытым исходным кодом Hibernate Types.
Затем вы можете просто объявить новый тип вашего класса.
@TypeDef(
name = "jsonb-node",
typeClass = JsonNodeBinaryType.class
)
И сопоставление сущностей будет выглядеть следующим образом:
@Type(type = "json-node")
@Column(columnDefinition = "json")
private JsonNode json;
Ответ №3:
Создайте ответ, не вводя логику в средство установки / получения объектов, без сторонних зависимостей:
ObjectNode node = JsonNodeFactory.instance.objectNode();
node.put("name", cat.getName());
node.set("json", new ObjectMapper().readTree(cat.getJson()));
return Response.ok(node).build();