# \[Proposal\] Entity classes

**URL:** <https://discuss.kotlinlang.org/t/proposal-entity-classes/25528>\
**Category:** Language Design\
**Created:** [August 25, 2022, 5:39pm UTC](https://discuss.kotlinlang.org/t/proposal-entity-classes/25528 "2022-08-25T17:39:50Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![homer-jay](https://avatars.discourse-cdn.com/v4/letter/h/71e660/32.png) [@homer-jay](https://discuss.kotlinlang.org/u/homer-jay)\
**Post date:** [August 25, 2022, 5:39pm UTC](https://discuss.kotlinlang.org/t/proposal-entity-classes/25528/1 "2022-08-25T17:39:50Z")

</div>

It would be nice to have something like a data class for entities. As you know, data classes generate `equals()` and `hashCode()` implementations using EVERY member in the class. While that is great for value objects, it is not ideal for entity classes.  
There could be a new keyword that generated `equals()` and `hashCode()` implementations using only those members that are “primary keys”.

Something like this:

```auto
entity class Foo(val id: String, val name: String) by id

```

or

```auto
entity class Bar(val id: String, val parentId: String, val name: String) by (id, parentId)

```

The most frequent use case would be to be able to compare local and remote objects using `equals()` considering only the PKs. For instance if we have a collection of cached entity objects, and we download new copies from the network, we could check if a remote object is already on the cache by id. With a data class, as soon as any non-PK field is different, `equals()` will return false. (Ok, maybe in this example that would actually be useful to detect ANY change in the object, but what if we just don’t care about the rest of the fields?). Another use case would be to use entity objects as HashMap keys, that way even if some non-PK field changes in a remote copy, the PK fields will still produce the same hash code and we could detect that it is already in the map.

I know this could be achieved with a bit of code using the current version of the language, but it is such a common use case that adding this feature would cut a lot of boilerplate. Not only that, it would put the language ahead of Java’s record classes.

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [August 25, 2022, 7:26pm UTC](https://discuss.kotlinlang.org/t/proposal-entity-classes/25528/2 "2022-08-25T19:26:27Z")

</div>

I would propose that this is not a common enough solution/use-case to warrant adding the language weight of a new class modifier.

Existing ORM frameworks have examples of how one could solve this. Alternatively, you could create an `Entity` parent class that takes properties as arguments. Another option is to use annotations either for marking the PKs or generating methods for comparison.

And there’s always the [minus 100 points](http://stronglyemergent.com/blog/2013/negative-100-points/) to consider. Adding a modifier isn’t a trivial thing to do to a language. This kind of change would require a decent amount of research with explanations and examples as to why the alternatives are not sufficient.

Luckily, there are so many close alternatives that would allow for testing out how it would work. For example, you could implement a compiler plugin that adds an `@Entity` annotation. That way you protect the language from the changes and get to experiment with the solution.

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [August 25, 2022, 7:38pm UTC](https://discuss.kotlinlang.org/t/proposal-entity-classes/25528/3 "2022-08-25T19:38:38Z")

</div>

I think what you try to do is conceptually wrong. You want to say `Foo(1, "john") == Foo(1, "james")` is true, which obviously is not. There is only one equals/hashCode per class and you want to fill it with implementation that is not really correct, but it helps you solve a very specific problem related to this class. What if then, in another functionality, you need to compare entities using a different set of properties or using all of them (e.g. you want to verify if entity was modified in relation to the one in the DB)?

You can create a separate class that holds unique props. This is much more clean and flexible, you can even have several such classes per entity to compare them differently in various places in your code. It requires some boilerplate, but I think this isn’t that bad:

```kotlin
class Bar(val id: String, val parentId: String, val name: String)
data class BarPK(val id: String, val parentId: String)
val Bar.pk get() = BarPK(id, parentId)

```

---

<div class="post-metadata">

**Author:** ![homer-jay](https://avatars.discourse-cdn.com/v4/letter/h/71e660/32.png) [@homer-jay](https://discuss.kotlinlang.org/u/homer-jay)\
**Post date:** [August 26, 2022, 12:44pm UTC](https://discuss.kotlinlang.org/t/proposal-entity-classes/25528/4 "2022-08-26T12:44:41Z")

</div>

> [@arocnies](#):
>
> you could create an `Entity` parent class

I could, but that might interfere with whatever inheritance there already is present (or might be added to) the entity classes. Even then, adding that utility parent class in every project is boilerplate. For maximum flexibility, you want to decouple inheritance from this, and instead follow a code generation approach.

> [@arocnies](#):
>
> you could implement a compiler plugin that adds an `@Entity` annotation

No, I’m afraid I could not. That is beyond beginner level.  
But even If I could, my past experience with Java is that littering the model with annotations is not a good thing.

---

<div class="post-metadata">

**Author:** ![homer-jay](https://avatars.discourse-cdn.com/v4/letter/h/71e660/32.png) [@homer-jay](https://discuss.kotlinlang.org/u/homer-jay)\
**Post date:** [August 26, 2022, 12:54pm UTC](https://discuss.kotlinlang.org/t/proposal-entity-classes/25528/5 "2022-08-26T12:54:38Z")

</div>

> [@broot](#):
>
> I think what you try to do is conceptually wrong. You want to say `Foo(1, "john") == Foo(1, "james")` is true, which obviously is not.

Well that is your very personal opinion. If it was always the case that we always need to check every single field, there would be no point in having `equals` nor `hashCode`, the compiler could generate those methods for every class.

But there are cases when we just need to check one or two fields instead of every single one. In fact this is instrumental for finding elements inside collections with a good performance, since most lists use `equals` in their `contains` or `indexOf` methods, and hashmaps use the `hashCode` in their `get`, `put`, and `containsKey` methods.

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [August 26, 2022, 1:08pm UTC](https://discuss.kotlinlang.org/t/proposal-entity-classes/25528/6 "2022-08-26T13:08:08Z")

</div>

> [@homer-jay](#):
>
> littering the model with annotations is not a good thing.

This is why littering a model with class modifiers is may not be a good thing. If you type it `@Entity` or `entity`, they have the same effect. A compiler plugin with an annotation is a much cheaper stepping stone than changing the compiler to add a class modifier.

To clarify, I suspect both an annotation and a modifier won’t be the best solution for this problem–I could be wrong. At least with an annotation you get to experiment with the idea, increment the version faster outside of the language, and protect the language from a costly addition of a new class modifier while you collect evidence.

I forgot to bring this up earlier but why not use comparators? After all, it better decouples the class from the responsibility to perform the comparison.

---

<div class="post-metadata">

**Author:** ![gidds](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/gidds/32/10865_2.png) [@gidds](https://discuss.kotlinlang.org/u/gidds)\
**Post date:** [August 26, 2022, 8:00pm UTC](https://discuss.kotlinlang.org/t/proposal-entity-classes/25528/7 "2022-08-26T20:00:59Z")

</div>

> [@homer-jay](#):
>
> As you know, data classes generate `equals()` and `hashCode()` implementations using EVERY member in the class.

This may be a nitpick, but that’s wrong: [data classes](https://kotlinlang.org/docs/data-classes.html) get an automatically-generated `equals()` and `hashCode()` (and `toString()` and `copy()` and `componentN()`) using all properties _declared in the primary constructor_.

Which presumably means that all you need to do is include the primary key in the primary constructor, and then declare all the remaining properties inside the class itself…?

But even if not, for me this doesn’t come close to beating the -100 points rule. In Kotlin, all those methods are one-liners if you’re only including one or two fields, so there’s much less boilerplate than you’d need in e.g. Java.

We already use compiler plugins, rather than language extensions, for Spring (e.g. to make certain classes and methods automatically `open`), so that seems a fairly good fit for this type of thing too.
