为来自不可修改的依赖关系的数据模型创建持久性(例如通过Spring Boot或仅通过JPA或Hibernate本身)的最佳实践是什么?典型的局限性如无法覆盖字段或Decorator之类的模式允许什么,以及哪些不会减慢我的进度。我尝试了一些事情,但最终总是得到以下结果:要么修改源模型(例如添加注释以使其与本机兼容->我不想要的fork),要么编写大量包装器代码这样会过多地复制原始模型-但这甚至无法正常工作:
我尝试了
JpaRepository
。不起作用,因为将扩展类强制转换为其父类无效。@Entity
)的自定义类扩展原始类,可以在此类存储库中使用。但是这里的问题是
@Id
注释,可以通过在扩展类中使用新的ID来解决此问题,但是@ElementCollection
,因为不能覆盖字段,所以不能添加这些注释。
Could not determine type for: java.util.List, at table: yeah_this_one, for columns:[org.hibernate.mapping.Column(objects)]
的错误表明无法完全隐藏原始字段(更改了新类中的表名和列名以进行验证)。@ElementCollection
(据说可以解决此问题)也无济于事。@AttributeOverride
也无法覆盖注解来设置ID或其他设置,只能更改名称和列。我一直处于这种状态,想知道这是否是正确的方法。
总体思路是基于这个Spring Boot REST tutorial,我尝试使用依赖项中的模型对其进行扩展。
我们假设存在不可修改的依赖项中的原始模型类Model
。 ModelEntity
将是扩展类,用作将模型引入Spring持久性的方式。
在依赖项的范围内,原始类将是:
// Given dependency, not modifiable
@Some existing annotation
public class Model extends AnotherClassFromDep {
@more annotations
private IdLikeClassFromDep modelId;
//more complex attribute
@Nullable
private List<RefClassFromDep> objects = new ArrayList<>();
// more attributes, getter, setter etc.
}
在我的程序范围内:
结合少量orm.xml
,可以将原始Model
注释为MappedSuperclass
,而无需修改(根据https://stackoverflow.com/a/2516951/1844976)。
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
<mapped-superclass class="package.name.of.original.Model">
</mapped-superclass>
</entity-mappings>
这允许创建这样的类,该类扩展了原始POJO模型以添加JPA注释:
@Entity
public class ModelEntity extends Model {
// some @Id attribute is necessary, which should correspond to
// the already existing ID attribute from the original `Model`
// in the best case, but an additional one would work too
private @Id @GeneratedValue Long id;
// Different approaches to solve the List error from above, for
// instance hiding the original attribute
@ElementCollection
private List<RefClassFromDep> objects;
public ModelEntity(){
super();
}
}
在当前状态下,这些问题使我无法继续前进。但是,我完全希望它可以与JpaRepository
一起使用:
// of course, creating a JpaRepository with original `Model` wouldn't
// work, because it has no `@Entity`
public interface ModelRepository extends JpaRepository<ModelEntity, IdLikeClassFromDep> {
}
以一种可能的方式实际访问它:
@Configuration
public class LoadDatabase {
@Bean
CommandLineRunner initDatabase(ModelRepository modelRepository) {
return args -> {
// depending on the implementation above, either create a
// Model and cast it or directly create a ModelEntity, set
// attriubtes and save it through the JpaRepository
modelRepository.save(model);
};
}
}
更抽象和更具体的与代码相关的想法和评论都将对我有所帮助。谢谢!
答案 0 :(得分:1)
过去,Jpa / Hibernate是通过XML配置的。
您需要提供git push repo1 +master:branch1
进行常规配置。在此文件中,您添加了persistence.xml
标记,该标记指向另一个文件<mapping-file>
。在该文件中,您为实体配置了映射(这些天通过JPA批注完成)。
尽管上述方法被认为是旧方法,但仍支持它们。 orm.xml
的方法LocalContainerEntityManagerFactoryBean
允许您指向setMappingResources
文件。搜索路径和默认位置有些时髦,但有据可查:
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html#setMappingResources-java.lang.String...-
请注意,您以此方式配置的第三方类需要符合Java Bean约定(无参数构造函数,getter和setter)