Joffrey
Joffrey

Reputation: 37710

Is @ManyToOne's "optional" param automatically set using Kotlin's nullability

I read that specifying optional = false in the @ManyToOne association annotation could help Spring improve the performance of the queries.

In a Kotlin data class entity, do I actually need to specify the parameter in the annotation, or can Spring figure this out by itself using the nullability of the item field?

For instance, if I have the following declaration:

@Entity
@Table(name = ACCESS_LOGS_ARCHIVES_TABLE, indexes = [
    Index(name = "access_logs_archives_item_idx", columnList = "access_item_id")
])
data class AccessLogArchive(
    val date: LocalDate,

    @ManyToOne(optional = false)
    @JoinColumn(name = "access_item_id", nullable = false) 
    val item: AccessLogItem,

    val occurrences: Int
) {
    @Id
    @GeneratedValue
    var id: Long? = null
}

@Entity
@Table(name = ACCESS_ITEMS_TABLE)
data class AccessLogItem(
    @Column(length = 3) val code: String,
    @Column(columnDefinition = "text") val path: String,
    @Column(length = 10) val verb: String
) {
    @Id
    @GeneratedValue
    var id: Long? = null
}

In this case, I would for instance expect Spring to know that the item field is not nullable, and thus the relationship should be understood as optional=false even without specifying it as I did. Is this the case?

Same question goes for the @JoinColumn's nullable = false, by the way.

Upvotes: 4

Views: 1675

Answers (1)

Willi Mentzel
Willi Mentzel

Reputation: 29844

Consider a simple entity like a Room which has a @ManyToOne relationship to House.

@Entity
class Room(
        @ManyToOne(optional = true)
        val house: House
) {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    val id: Long = 0
}

JPA will create a room table with a column

`house_id` bigint(20) DEFAULT NULL

If you specify @ManyToOne(optional = false)

the column will look like this:

`house_id` bigint(20) NOT NULL

By specifiying optional you tell JPA how the schema should be generated, whether the column can be NULL or not.

At runtime trying to load a Room without a House will cause an Exception if the house property is not nullable (House instead of House?) even when value of optional is true.

The same applies to @JoinColumn.

Is @ManyToOne's “optional” param automatically set using Kotlin's nullability?

No it is not. It is independent from that and by default set to true.

Conclusion: In order for you schema to reflect your entities it is a good idea to use optional = true if the house property would be nullable and optional = false if the house property would be non-nullable.

Upvotes: 1

Related Questions