介绍
开源的hibernate-types
项目允许您将Java对象或Jackson JsonNode
为JPA实体属性。
最近,感谢我们的杰出贡献者,我们添加了对类型安全集合的支持,该集合也可以作为JSON持久化。 在本文中,您将了解如何实现此目标。
Maven依赖
首先,您需要在项目pom.xml
配置文件中设置以下Maven依赖项:
<dependency><groupId>com.vladmihalcea</groupId><artifactId>hibernate-types-52</artifactId><version>${hibernate-types.version}</version>
</dependency>
如果您使用的是较早版本的Hibernate,请查看hibernate-types
GitHub存储库 ,以获取有关当前Hibernate版本的匹配依赖项的更多信息。
领域模型
假设我们具有以下Location
Java对象类型。
public class Location implements Serializable {private String country;private String city;//Getters and setters omitted for brevity@Overridepublic String toString() {return "Location{" +"country='" + country + '\'' +", city='" + city + '\'' +'}';}
}
并且,一个Event
实体:
@Entity(name = "Event")
@Table(name = "event")
public class Event extends BaseEntity {@Type(type = "jsonb")@Column(columnDefinition = "jsonb")private Location location;@Type(type = "jsonb",parameters = {@org.hibernate.annotations.Parameter(name = TypeReferenceFactory.FACTORY_CLASS,value = "com.vladmihalcea.hibernate.type.json.PostgreSQLGenericJsonBinaryTypeTest$AlternativeLocationsTypeReference")})@Column(columnDefinition = "jsonb")private List<Location> alternativeLocations = new ArrayList<Location>();//Getters and setters omitted for brevity
}
BaseEntity
定义了一些基本属性(例如@Id
@Version
, @Id
@Version
)和几种海关Hibernate类型,其中,我们对JsonBinaryType
感兴趣。
@TypeDefs({@TypeDef(name = "string-array", typeClass = StringArrayType.class),@TypeDef(name = "int-array", typeClass = IntArrayType.class),@TypeDef(name = "json", typeClass = JsonStringType.class),@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class),@TypeDef(name = "jsonb-node", typeClass = JsonNodeBinaryType.class),@TypeDef(name = "json-node", typeClass = JsonNodeStringType.class),
})
@MappedSuperclass
public class BaseEntity {@Idprivate Long id;@Versionprivate Integer version;//Getters and setters omitted for brevity
}
有关使用@MappedSuperclass
更多详细信息,请@MappedSuperclass
本文 。
TypeReferenceFactory
要将Location
对象存储在jsonb
PostgreSQL列中,我们只需要使用@Type(type = "jsonb")
注释location
属性。
但是,对于alternativeLocations
集合,我们需要提供关联的Jackson TypeReference
以便在从关系数据库中读取JSON对象时可以重建非常相同的类型安全的Java集合。
为此,我们提供TypeReferenceFactory
实现的完全限定的类,如下所示:
public static class AlternativeLocationsTypeReference implements TypeReferenceFactory {@Overridepublic TypeReference<?> newTypeReference() {return new TypeReference<List<Location>>() {};}
}
而已!
测试时间
保存以下Event
实体时:
Location cluj = new Location();
cluj.setCountry("Romania");
cluj.setCity("Cluj-Napoca");Location newYork = new Location();
newYork.setCountry("US");
newYork.setCity("New-York");Location london = new Location();
london.setCountry("UK");
london.setCity("London");Event event = new Event();
event.setId(1L);
event.setLocation(cluj);
event.setAlternativeLocations(Arrays.asList(newYork, london)
);entityManager.persist(event);
Hibernate将生成以下SQL INSERT语句:
INSERT INTO event (version, alternativeLocations, location, id
)
VALUES (0, [{"country":"US","city":"New-York"},{"country":"UK","city":"London"}], {"country":"Romania","city":"Cluj-Napoca"}, 1
)
此外,检索回时Event
实体,无论是location
,并the
alternativeLocations`属性是正确的获取:
事件event = entityManager.find(Event.class,eventId);
assertEquals("Cluj-Napoca", event.getLocation().getCity()
);assertEquals(2, event.getAlternativeLocations().size());assertEquals("New-York", event.getAlternativeLocations().get(0).getCity()
);
assertEquals("London", event.getAlternativeLocations().get(1).getCity()
);
酷吧?
翻译自: https://www.javacodegeeks.com/2017/12/map-json-collections-using-jpa-hibernate.html