2015-09-04 40 views
3

使用彈簧持久性但保持不可變類型我已將PersistenceConstructor註釋添加到我的數據類中。這告訴spring在從數據庫加載類時使用該構造函數。使用默認值對Kotlin數據類的Spring構造函數註解

但是,我很難找到構造函數的春天。

data class MyData @PersistenceConstructor constructor(@Id val id: Int? = null, val a:String) 

這在我的機器上100%的時間工作,但是當部署到heroku時,它始終失敗。

看起來,通過參數的默認值kotlin會生成多個構造函數,但問題是每個構造函數都會得到應用於它們的註釋,所以它只是運行(或特定於jdk實現)哪一個彈簧會啓動。默認的參數沒有參數的名字,所以Spring不知道如何處理它。

我真正的構造函數比這個大,所以沒有默認值會很痛苦。有沒有辦法讓註釋只適用於沒有默認值的構造函數?

+0

現在Kotlin中還存在其他選項,我添加了一個覆蓋@JvmOverloads [在M12中添加](http://blog.jetbrains.com/kotlin/2015/05/kotlin-m12-is-out/) –

+0

的答案它似乎是JvmOverloads的副作用,因爲在Kotlin數據類中沒有構造函數參數名稱的實際問題。其實看起來像kotlin中的bug –

回答

2

目前我的答案是定義兩個構造函數。一個供我使用的默認設置,一個供Spring使用,沒有默認設置。

data class MyData @PersistenceConstructor constructor(val a: Int?, val b:String, val c : Collection<Int>) { 
    constructor(a: Int? = null, b: String = "", c: Collection<Int> = emptyList()) : this(a,b,c) 
} 

我不喜歡它的重複,所以它不是我的首選解決方案。

+0

在沒有任何其他答案的情況下,我將此標記爲可接受的解決方案,但仍對其他更簡單的選項感興趣。 –

+1

Kotlin支持這個答案,而無需採取這種解決方法。查看發佈的其他答案。 –

9

您可以使用@JvmOverloads annotation,這將自動創建可由Java調用的方法的排列並利用默認值。

從文檔,這個例子:

@JvmOverloads fun f(a: String, b: Int = 0, c: String = "abc") { 
    ... 
} 

將會從Java被視爲:

// Java 
void f(String a, int b, String c) { } 
void f(String a, int b) { } // will default c 
void f(String a) { } // will default b and c 

你的情況是觸摸不同的位置有一個默認的參數,後面跟着一個不是。簡化您的例子:

data class MyData @JvmOverloads constructor(val id: Int? = null, val a:String) 

產生從Java這樣的觀點:

// java 
MyData(Int id, String a) 
MyData(String a) // defaults id 

您可以在科特林參考閱讀更多有關Java calling Kotlin interoperability