2016-08-05 36 views
0

我目前正在創建一個產品,我的意思是一個應用程序比它擁有的應用程序要多,但它的結構可以爲不同的客戶端定製。爲代碼庫設計可擴展實體

在後臺使用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{...} 

所以我的問題是會是什麼考慮以下限制是最好的處理方法:

  • No ful l抽象數據庫模型(比如有一個大的實體表和一個大的屬性表)。
  • 我使用傑克遜,所以當我有繼承我必須註釋/更改超類的註釋。
  • JPA/Jackson註釋是在同一個類上,我不想盡可能重複我的模型的類並保持它的集中。

這裏是我雖然關:

地圖擴展屬性:

  • 每個支持此項目類型再添加一個表。
  • 數據庫可讀性較差
  • 無法在數據庫中應用任何約束。贊同

用法:

  • 重寫實體相同的封裝和相同的名字,並把它認可的文件夾中,他們當然只能增加新的領域。
  • 數據庫仍然可讀和清潔
  • 一般來說,不推薦使用背書,但它是可用的,所以它可以是值得的。

注意我目前使用hibernate4,但如果需要我可以升級到5.同樣,如果您的解決方案是使用註釋而不是XML,我可能會稍後切換到註釋,但不是今天。

任何替代品的貢獻,即使它不符合我的要求,歡迎。

回答

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> 

因此,既然你將能夠添加新的實體,即使它不是在同一個包。

添加繼承實體

爲了添加屬性/擴展需要添加inheritancy對象。對於層次結構JOIN繼承不會花費太多,只要您正確地將唯一約束和外鍵添加到適當的字段即可。

@Inheritance(strategy=InheritanceType.JOINED) 

如果你現在不能,因爲你不能修改超可能有2種選擇:休眠的

  • 獲取源

    • 使用XML配置(原始或.class)或類,添加註釋,將其包裝到jar中,並將其放入服務器/應用程序的支持文件夾中,並且不要忘記啓用支持的機制。

    嚴格來說,使用背書是危險的,必須非常仔細地完成。對於那些不知道的人,當你啓用支持機制時,你需要指定一個文件夾,其中所有的jar文件將在每個類之前加載。即使是JRE也是如此,所以您可以確保該文件夾中的類將被加載而不是其他JAR中的類。

    傑克遜:使用混合式繼承

    通常與傑克遜,你需要添加註釋@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{ 
    
    }