jakartaee / jakartaee/persistence

consider adding JDBC type to @Column or a zoo of built-in AttributeConverters

Open
#619 11 comments 0 reactions 0 assignees Claimed by @gavinking View on GitHub
candidate-for-4
Dominant language
Java
Stars
267
Forks
78
Avg merge
1d 6h
Merged PRs (30d)
13

Description

Currently there are two ways to customize the column type mapped by a field:

1. using an `AttributeConverter`, or
2. using `@Column(columnDefinition)`.

An `AttributeConverter` works very well for basic types, but there are no built-in `AttributeConverter`s, and it's a pain for the user to have to write one. And it doesn't work at all for associations.

On the other hand `columnDefinition` doesn't work very well, for several reasons, including that it's not at all portable between databases, and also doesn't do any sort of type conversion at the Java level.

First approach
---

Since very ancient times, Hibernate allowed the column type to be customized in a portable way by specifying a JDBC type code from the list given in `java.sql.Types`. Today this is usually done via the `@JdbcTypeCode` annotation.

The only thing about this approach that has always left me a little uncomfortable is the lack of typesafety, due to the `Types` being integers. A way to alleviate this discomfort would be to use the `JDBCType` enumeration instead. So we could add:

```java
public @interface Column {
...
JDBCType type() default JDBCType.OTHER;
}
```

where we would be abusing `OTHER` to mean "default".

So I could write:

```java
@Column(type=JDBCType.DECIMAL)
int total;
```

The spec would need to define which combinations of (field type, JDBC type) an implementation is required to support, but just like with the JPQL `cast()` function, that list need not be extremely long. That is, it could, at least initially, just be basic numeric conversions and conversions to `varchar`.

Second approach
---

Alternatively, if this abuse of `OTHER` is unacceptable, we could add a new annotation:

```java
public @interface ColumnType {
JDBCType value();
}
```

which might anyway be a cleaner approach.

I would write:

```java
@ColumnType(JDBCType.DECIMAL)
int total;
```

Third approach
---

Alternatively, the specification could provide a set of built-in attribute converter classes, for use with `@Convert`. The problem is that to provide converters for _n_ Java types to _m_ JDBC types requires _nm_ classes, which gets a bit messy.

It would look like:

```java
@Convert(converter=Converters.IntegerToDecimal.class)
int total;
```

which is a bit more verbose than the previous options.

The advantage of this approach is that it requires no new concept in the spec. The major disadvantage is that attribute converters are disallowed for primary and foreign key columns.

Contributor guide

Open the contributing guide

Research direction

Review the proposed approaches around @Column, @JdbcTypeCode, JDBCType, AttributeConverter, and @Convert, then inspect the linked pull request #819. The issue is complete only after the project settles on one design and defines the supported Java-to-JDBC mappings or built-in converters.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, sql
Domain
backend-api-design, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.