我目前正在创建一个产品,我的意思是一个应用程序而不是它所拥有的应用程序,但它的结构可以为不同的客户端定制。
在后台使用spring可以很容易地改变服务/控制器的实现,我只是重载bean。客户端我有angularJS,我可能需要重组模块并提供更多的灵活性,但这也应该很容易。
我唯一的问题在于JPA / Hibernate实体。
以下是我的配置:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan">
<array>
<value>com.xxx.entity</value>
</array>
</property>
<property name="persistenceUnitName" value="MyPU" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">${hibernate.show.sql}</prop>
<prop key="hibernate.format_sql">${hibernate.show.sql}</prop>
<prop key="hibernate.dialect">${database.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<!-- <prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory</prop> -->
</props>
</property>
<!-- <property name="sharedCacheMode" value="ENABLE_SELECTIVE" /> -->
</bean>
现在让我们考虑产品中的以下对象,并为两个不同的客户端进行两次自定义:
// let's say this one is the basic one
class People{ String firstName;String lastName;}
// one client want us to add one felds
class PeopleClientOne extends People{String address;}
// another define two type of very different people while having one more field common for them
class People{String firstName; String lastName;String anotherField;}
class PeopleOneClientTwo extends People{...}
class PeopleTwoClientTwo extends People{...}
所以我的问题是考虑到以下限制,最好的办法是什么:
以下是我的意思:
可扩展属性的地图:
背书的使用:
注意我目前正在使用hibernate4但是如果需要我可以升级到5.如果您的解决方案是注释而不是XML,我可能会在以后切换到注释但不是今天。
任何替代贡献,即使它没有遵循我的要求,也欢迎。
答案 0 :(得分:1)
在这里,我最终能够:
摆脱仅修复一个软件包的数组
将数组定义为列表:
<util:list id="entityPackages">
<value>my.package.com.entity</value>
</util:list>
注入时使用EL转换为数组:
<property name="packagesToScan" value="#{entityPackages.toArray()}"/>
必要时在自定义客户端模块中重载:
<!-- either import file containing the old one or use profile -->
<util:list id="entityPackages">
<value>my.package.com.entity</value><!-- need to repeat that -->
<value>my.package.com.subentity</value>
</util:list>
因此,即使它不在同一个包中,您也可以添加新实体。
向实体添加继承
要添加属性/扩展对象,您需要添加继承。对于层次结构,只要将唯一约束和外键正确添加到适当的字段,JOIN继承就不会花费太多。
@Inheritance(strategy=InheritanceType.JOINED)
如果您现在无法修改超类,那么您可能有两种选择:
严格地说,使用背书是危险的,必须非常小心。对于那些不知道的人,当你启用了支持机制时,你指定一个文件夹,在每个类之前将加载所有jar文件。即使是JRE,也可以确保该文件夹中的类是加载的,而不是其他JAR中的类。
杰克逊:使用混合来继承
通常使用Jackson,您需要添加注释@JsonSubTypes,这会强制您将母班与子类相关联。为了使这个类与这些孩子保持独立,你可以使用mixIn注释:
// make that bean get injected the instance of jackson's mapper and called either during the initialization or just after the spring's application context was loaded.
public afterStartup() {
myJackSonMapper.addMixIn(Site.class, SiteInheritanceMixIn.class);
}
// considering here that SubSite is inheriting from Site
@JsonSubTypes({
@JsonSubTypes.Type(value = SubSite.class, name = "subSite")
})
public abstract class SiteInheritanceMixIn{
}