Using Sugar ORM with Kotlin


#1

I'm trying to use Sugar ORM with Kotlin, and the docs here asks that we retain the default constructor. Since Kotlin currently doesn't quite support secondary constructors, how should I go about handling this?


#2

If you provide default values for all you rconstructor parameters, Kotlin will generate a default constructor for you:

class Foo(a: Int = 0, b: String = "") { ... }


#3

Great! That was what I was hoping for. A lot of Java interop issues tend to boil down to implementation details, so it can be hard to get a handle on them sometimes.


#4

abreslav wrote:

If you provide default values for all you rconstructor parameters, Kotlin will generate a default constructor for you:

class Foo(a: Int = 0, b: String = "") { ... }

But this is far from optimal. Quite often this is used for entities which tend to have many fields and IIUIC, Kotlin would generate n+1 constructors. What's worse, they'd visible in Kotlin, so you can't rely on

val foo = Foo(1, 2, “a”, 4, 5, “b”)

to assure that you haven’t forgotten an argument. What about an annotation like

class [NoArgsConstructor] Foo(a: Int, b: String) { … }

simply generating a single constructor using Java default values? Or even

class [NoArgsConstructor(accessible=false)] Foo(a: Int, b: String) { … }

generating such a constructor, but making it inaccessible from normal code (so serialiazation and ORM would work, but you wouldn’t see it anywhere)?


#5

Quite often this is used for entities which tend to have many fields and IIUIC, Kotlin would generate n+1 constructors.

No, for now there will one default constructor generated.

What about an annotation like

class [NoArgsConstructor] Foo(a: Int, b: String) { … }

simply generating a single constructor using Java default values?

This doesn’t seem like a reliable approach. Javadefault values may or may not be reasonable defaults for the particular domain object, and nullability of references will be compromized 100%


#6

Quite often this is used for entities which tend to have many fields and IIUIC, Kotlin would generate n+1 constructors.

No, for now there will one default constructor generated.

OK, I expected that it works like in other languages, where f(a=1, b=2) is a shortcut for three methods f(), f(a), and f(a, b).

What about an annotation like

class [NoArgsConstructor] Foo(a: Int, b: String) { … }

simply generating a single constructor using Java default values?

This doesn’t seem like a reliable approach. Javadefault values may or may not be reasonable defaults for the particular domain object, and nullability of references will be compromized 100%


Right, but IIRC de-serialization of a class inheriting from a non-serializable superclass requires(*) some no-args constructor in the superclass and it doesn’t matter what it does, as the fields get overwritten anyway. Similarly the ORM tools need to get any instace just to overwrite all its fields. My point was more about hiding the dumb constructor.

(*) This may have changed as it uses Unsafe.


#7

I see what you mean, we'll look into it.


#8

Hello! Any news about this? I would love see this feature on data classes, to use with JPA.

If there was an annotation to create a non arg constructor on JVM, we don’t need to provide this secondary constructor to every entity:

@Entity
data class Person(

    @Id @GeneratedValue
    val id: Long? = null,

    val name: String,

    val age: Int

) : Serializable {

    private constructor() : this(name = "", age = 0)

}

Isn’t a good design provide imaginary value just to make the ORM happy.

This doesn’t seem like a reliable approach. Javadefault values may or may not be reasonable defaults for the particular domain object, and nullability of references will be compromized 100%

Instead provide a Java default value, lateinit principle is a good approach. The ORM tool always will override all values. This will not compromise nullability.


#9

It’s not so easy to implement this without compromising semantics: a user-defined constructor of this class may have important logic in it that will be lost if someone called a generated no-arg one… I guess, it’s possible to work around this, but it’s tricky.


#10

a user-defined constructor of this class may have important logic in it that will be lost if someone called a generated no-arg one

This modifier annotation could be allowed only in data-classes that only define properties on constructor.
To create a entity model is more than sufficient.

This non arg constructor, when called, could late initializing all properties declared on primary constructor.

See my own post about this, over there I’ve explained better what is my propose: Feature request: A modifier annotation for data classes to provide a non arg constructor on JVM


#11

For the reference: here is a related discussion