开发无Hibernate依赖通用库,如何让库类成为Hibernate Embeddable?
当然有办法!不用子类化,也不用修改你库里的Interval类,就能让它在Hibernate项目里成为可嵌入类(Embeddable)。核心是用Hibernate的无侵入式映射方式,下面给你两种实用方案:
方案1:使用Hibernate XML映射文件(推荐)
这是最经典的无侵入映射方式,完全不需要改动库中的类,只需要在使用Hibernate的项目里添加一个XML配置文件:
- 在项目的资源目录(比如
src/main/resources)下创建映射文件,命名为Interval.hbm.xml - 写入以下内容,把
Interval标记为<embeddable>,并映射它的start和end字段到数据库列:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.yourlibrary.model"> <embeddable class="Interval"> <property name="start" column="interval_start" type="java.time.Instant"/> <property name="end" column="interval_end" type="java.time.Instant"/> </embeddable> </hibernate-mapping>
让Hibernate扫描到这个配置文件:
- 如果是传统Hibernate项目,在
hibernate.cfg.xml里添加:<mapping resource="Interval.hbm.xml"/> - 如果是Spring Boot项目,在
application.properties里配置:spring.jpa.hibernate.mapping-resources=Interval.hbm.xml
- 如果是传统Hibernate项目,在
在你的实体类中直接使用
@Embedded注解引用Interval即可:
@Entity public class Event { @Id private Long id; @Embedded private Interval timeRange; // 其他字段、getter/setter }
方案2:编程式映射API
如果你更喜欢纯代码配置,不想用XML,可以用Hibernate的编程式映射API来动态注册Interval为可嵌入类:
传统Hibernate项目配置
import org.hibernate.boot.MetadataSources; import org.hibernate.mapping.Embeddable; import org.hibernate.mapping.Property; import org.hibernate.type.StandardBasicTypes; public class HibernateSetup { public void configureHibernate() { MetadataSources metadataSources = new MetadataSources(); // 注册Interval为可嵌入类 Embeddable intervalEmbeddable = metadataSources.addEmbeddable(Interval.class); // 映射start属性到数据库列interval_start Property startProp = new Property(); startProp.setName("start"); startProp.setType(StandardBasicTypes.INSTANT); startProp.setValue(intervalEmbeddable.createComponentPropertyValue("interval_start")); intervalEmbeddable.addProperty(startProp); // 映射end属性到数据库列interval_end Property endProp = new Property(); endProp.setName("end"); endProp.setType(StandardBasicTypes.INSTANT); endProp.setValue(intervalEmbeddable.createComponentPropertyValue("interval_end")); intervalEmbeddable.addProperty(endProp); // 后续继续构建SessionFactory... } }
Spring Boot项目集成
可以通过HibernatePropertiesCustomizer来无缝整合:
import org.hibernate.boot.MetadataBuilderContributor; import org.hibernate.boot.MetadataSources; import org.hibernate.mapping.Embeddable; import org.hibernate.mapping.Property; import org.hibernate.type.StandardBasicTypes; import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; import org.springframework.stereotype.Component; import java.util.Map; @Component public class IntervalEmbeddableConfig implements HibernatePropertiesCustomizer { @Override public void customize(Map<String, Object> hibernateProperties) { hibernateProperties.put("hibernate.metadata_builder_contributor", (MetadataBuilderContributor) metadataBuilder -> { MetadataSources sources = metadataBuilder.getMetadataSources(); Embeddable intervalEmbeddable = sources.addEmbeddable(Interval.class); // 配置start属性 Property startProp = new Property(); startProp.setName("start"); startProp.setType(StandardBasicTypes.INSTANT); startProp.setValue(intervalEmbeddable.createComponentPropertyValue("interval_start")); intervalEmbeddable.addProperty(startProp); // 配置end属性 Property endProp = new Property(); endProp.setName("end"); endProp.setType(StandardBasicTypes.INSTANT); endProp.setValue(intervalEmbeddable.createComponentPropertyValue("interval_end")); intervalEmbeddable.addProperty(endProp); }); } }
注意事项
- 两种方案都完全不需要修改你库中的
Interval类,也不用子类化,完美实现了库的通用性和Hibernate项目的适配性 - 确保你的Hibernate版本支持
java.time.Instant(Hibernate 5.2+已经原生支持,旧版本可能需要额外的类型转换器)
内容的提问来源于stack exchange,提问作者qnhant5010
相关产品推荐
相关产品推荐

