JPA原生查询映射POJO类与PostgreSQL上的JSONB值
问题描述:
我试图从多个表检索使用本机查询到一个自定义POJO联合值。我想要检索的其中一个值是JSONB字段。虽然我能够使用该字段获取实体,但是当我将其强制到自定义POJO中时,出现'org.hibernate.MappingException:无法映射JDBC类型:1111'异常。以下是我使用的:JPA原生查询映射POJO类与PostgreSQL上的JSONB值
CREATE TABLE book (
id BIGSERIAL NOT NULL PRIMARY KEY,
data JSONB NOT NULL
);
CREATE TABLE price (
book_id BIGSERIAL NOT NULL PRIMARY KEY,
price NUMERIC(19,2) NOT NULL
);
INSERT INTO book (id, data) VALUES (0, '{"value": "someValue"}');
INSERT INTO price (book_id, price) VALUES (0, 10.00);
使用POJO的:
@Entity
@TypeDef(defaultForType = MyJson.class, name = "MyJsonType", typeClass = MyJsonType.class)
@Data
@SqlResultSetMapping(name = "CustomMapping",
classes = {
@ConstructorResult(targetClass = CustomPOJO.class,
columns = {@ColumnResult(name = "id"),
@ColumnResult(name = "data"),
@ColumnResult(name = "price")})
})
public class Book {
@Id
@GeneratedValue
Long id;
@Column(nullable = false, columnDefinition = "JSONB")
MyJson data;
}
有了它的MyJson类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyJson implements Serializable {
private String value;
}
而且
@Entity
@Data
@NoArgsConstructor
public class Price {
@Id
private Long id;
private BigDecimal price;
}
而且我的自定义POJO
@AllArgsConstructor
@Data
public class CustomPOJO {
private Long id;
private MyJson data;
private BigDecimal price;
}
'@TypeDef'自定义方言映射的执行方式与this类似。 @SqlResultSetMapping我从here得到。 现在,我尝试使用我的自定义映射查询:
String query = "SELECT id, data, price\n" +
"FROM book, price\n" +
"WHERE book.id = price.book_id;";
Query nativeQuery = em.createNativeQuery(query, "CustomMapping");
@SuppressWarnings("unchecked")
List<CustomPOJO> customPOJOS = nativeQuery.getResultList();
我意识到,当我用我的自定义SqlResultSetMapping注释,Hibernate并不认识的类型定义。我该如何解决这个问题?请注意,我不能使用TypedQueries,因为我的实际查询是复杂的,而我可以用JPA查询语法处理。如有必要,我可以在github上上传一个示例项目。
答
我设法解决它。事实证明,您需要告诉SqlResultSetMapping中的每个列应该表示哪种类型。对于字段类MyJson的Jsonb字段,您需要使用自定义的UserType类'MyJsonType'(Implementation on this Site)。这看起来是这样的:
@SqlResultSetMapping(name = "CustomMapping",
classes = {
@ConstructorResult(targetClass = CustomPOJO.class,
columns = {@ColumnResult(name = "id", type = Long.class),
@ColumnResult(name = "data", type = MyJsonType.class),
@ColumnResult(name = "price", type = BigDecimal.class)})
})
很显然,你需要适当的构造函数自定义POJO类,在我的例子,多数民众赞成与@AllArgsConstructor注释照顾。
看看这个教程:http://www.thoughts-on-java.org/persist-postgresqls-jsonb-data-type-hibernate/ –
这就是我第一次使用(我甚至连接它)。问题是,只要我使用SqlResultSetMapping,自定义方言就不会被识别。 – SlideM