DEV Community

Mapping JPA entities with Kotlin

Livio Ribeiro on November 10, 2017

Kotlin is a very interesting programming language created by JetBrains that runs on the JVM. One of its features is data classes, which are class...
Collapse
 
tonyengineering profile image
tony-engineering

Hello,

Thanks for your article.

I wrote a code based on what you wrote, and have difficulties to persist an entity in the database.

javax.persistence.PersistenceException: No Persistence provider for EntityManager named PersistenceProviderMysql

    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
    at KrakenConnector.saveLastPrice(KrakenConnector.kt:42)
    at KrakenConnector.getAndSaveLastPrice(KrakenConnector.kt:17)

I added a persistence.xml file at the following path: src/main/resources/META-INF

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="PersistenceProviderMysql" transaction-type="RESOURCE_LOCAL">
        <class>KrakenConnector</class>
        <properties>
            <!-- Configuring The Database Connection Details -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpaDemoDb" />
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="" />
        </properties>
    </persistence-unit>
</persistence>

And the code to persist my entity is:

fun saveLastPrice(ohlcs: KrakenOHLCs) {
        val krakenOHLCsPersistable = KrakenOHLCsPersistable(ohlcs.ohlCs, 1)

        val emFactory: EntityManagerFactory = Persistence.createEntityManagerFactory("PersistenceProviderMysql")
        val entityManager = emFactory.createEntityManager()
        entityManager.transaction.begin()
        entityManager.persist(krakenOHLCsPersistable)
        entityManager.transaction.commit()
        entityManager.close()
        emFactory.close()
    }

I added "javax.persistence-api" version 2.2 as dependency in my pom.xml and also enabled the JPA support as described here kotlinlang.org/docs/reference/comp....

I am pretty sure the persistence.xml file is not detected because the error is the same when I delete it.

Could you provide the full working code of your example so I can try to reproduce it ?

Thanks in advance for your help,
Tony

Collapse
 
felipebelluco profile image
Felipe Belluco • Edited

Shouldn't I have to declare @JoinColumn(name = "task_list_id")? I keep getting the following error:

ERRO: column planos0_.convenio_id_convenio does not exist

In my case, Plano is task and Convenio is TaskList.

Collapse
 
00babe9 profile image
00babe9

Hi, Livio! Great post. I'm interested in how to do deletions in onetomany relation. Im looking for help. I have User Role classes, and I want, when I deleting my Role, I want to kill relation link on User(role_id = null, like so on). How can I achieve this?

Collapse
 
ksambhavjain profile image
Kumar Sambhav Jain

Short & sweet.
In most cases I find that common entity fields like id, verison, dateCreated, lastUpdated are pulled up in a super base entity class. Could you please explain that scenario too ?

Collapse
 
livioribeiro profile image
Livio Ribeiro

Sorry for the late reply.

I did some tests and found out that inheritance with data classes can be tricky, specially if you have to set fields on the base class, since you cannot have arguments on the primary constructor that are not properties.

If the fields in the base class are auto generated (like Id, creation date), you can do something like this:

import java.time.LocalDate
import java.time.LocalDateTime

open class Base(
        val id: Int? = null,
        val dateCreated: LocalDateTime = LocalDateTime.now(),
        val lastUpdated: LocalDateTime = LocalDateTime.now(),
)

data class Task(
        var name: String,
        var description: String? = null,
        var dueDate: LocalDate? = null,
        var done: Boolean = false
) : Base()

For more complex cases, I believe it is better to use normal classes.

Collapse
 
chrisvasqm profile image
Christian Vasquez

I love it every time I get a DEV post as a Google search result in the first 5 or so links!

Thanks for sharing this, Livio :)