简体   繁体   中英

Java -> Kotlin. Data classes conversion pattern

I am writing a Spring Boot application with maven. But recently I upgraded JDK to 10, and Lombok stable stopped working with it. I decided that it will be a great excuse to start using Kotlin. But I am not happy with the look of data classes of Kotlin with spring boot application.

example Java:

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(exclude = {"creator", "content"})
public class Document {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    private String id ;

    @Size(min = 4, max = 100)
    private String name;

    @ManyToOne
    @Column(updatable = false)
    private User creator;

    @OneToOne(cascade = CascadeType.ALL)
    private Content content;

    @ManyToOne
    private Project project;

    @NotNull
    @Column(updatable = false)
    @JsonFormat(pattern = "yyyy/MM/dd hh:mm:ss")
    private LocalDateTime creationDate;

    @NotNull
    @LastModifiedDate
    @JsonFormat(pattern = "yyyy/MM/dd hh:mm:ss")
    private LocalDateTime lastModified;

    @ManyToOne
    @LastModifiedBy
    private User modificator;
}

example Kotlin:

@Entity
data class Document(@Id
                @GeneratedValue(generator = "uuid2")
                @GenericGenerator(name = "uuid2", strategy = "uuid2")
                val id: String,
                @Size(min = 4, max = 100)
                val name: String,
                @ManyToOne
                @JoinColumn(updatable = false)
                private val creator: User,
                @OneToOne(cascade = arrayOf(CascadeType.ALL))
                private val content: Content,
                @ManyToOne
                @JoinColumn(updatable = false)
                val project: Project,
                @NotNull
                @Column(updatable = false)
                @JsonFormat(pattern = "yyyy/MM/dd hh:mm:ss")
                val creationDate: LocalDateTime,
                @NotNull
                @LastModifiedDate
                @JsonFormat(pattern = "yyyy/MM/dd hh:mm:ss")
                private val lastModified: LocalDateTime,
                @ManyToOne
                @LastModifiedBy
                private val modificator: User
)

which makes my code really unreadable. Do you have any template how spring boot data classes should be written? Or how to convert existing Java classes to Kotlin using all of Kotlin benefits?

I am using IntelliJ Idea Community edition 2018.1. Or maybe you have a better idea to persist Lombock like model classes?

Kotlin data classes allow for a level of concision and efficiency that you can't get with POJOs. I use this pattern that you're looking for extensively in my projects at work.

And, yes, they look similar to that. However, there are some inefficiencies in your code that can be easily bypassed. For example, there isn't any point in nullability annotations when the language has it built-in.

Here's one of my project classes, as an example of real-world use:

@Entity
@Table(name = "Acks")
data class AckEntity(
        @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
        val id: Int = 0,

        @Enumerated(EnumType.STRING)
        val ackType: AckType,

        @OneToOne(cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
        @JoinColumn(name = "alert")
        val alert: AlertEntity,

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn
        val session: SessionEntity? = null,

        @Embedded
        val sale: SaleEntity?,

        val version: Int,
        val timestamp: Date?) : DataEntity

Compared to how these classes used to look in Java, I'd say that this is far-and-away a cleaner approach.

However, it might just take some time to get used to how Kotlin does things. Once you learn how to speed-read the language though, I think you'll see your efficiency increase quite a bit. I know I did.

You don't have to convert the Model classes to Kotlin if you don't like the look of it. Kotlin can just pick up .java classes. Otherwise you can do something like, btw this is just an automatic conversion in intelliJ.

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(exclude = { "creator", "content" })
class Document {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    var id: String? = null
        set(id) {
            field = this.id
        }

    @Size(min = 4, max = 100)
    var name: String? = null
        set(name) {
            field = this.name
        }

    @ManyToOne
    @Column(updatable = false)
    var creator: User? = null
        set(creator) {
            field = this.creator
        }

    @OneToOne(cascade = CascadeType.ALL)
    var content: Content? = null
        set(content) {
            field = this.content
        }

    @ManyToOne
    var project: Project? = null
        set(project) {
            field = this.project
        }

    @NotNull
    @Column(updatable = false)
    @JsonFormat(pattern = "yyyy/MM/dd hh:mm:ss")
    var creationDate: LocalDateTime? = null
        set(creationDate) {
            field = this.creationDate
        }

    @NotNull
    @LastModifiedDate
    @JsonFormat(pattern = "yyyy/MM/dd hh:mm:ss")
    var lastModified: LocalDateTime? = null
        set(lastModified) {
            field = this.lastModified
        }

    @ManyToOne
    @LastModifiedBy
    var modificator: User? = null
        set(modificator) {
            field = this.modificator
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM