Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

@ColumnName with MySQL tinyint(1) and Java booleans

389 views
Skip to first unread message

northCoder

unread,
Apr 4, 2021, 1:15:54 PM4/4/21
to jDBI
When using the @ColumnName annotation, I have typically placed it on a field. Here is an example from the documentation showing this:

public class User {
    @ColumnName("user_id")
    public int id;

    public String name;
}

This all worked as expected with text, numbers and dates, until I tried to use a Java boolean field to receive the value of a MySQL tinyint(1) column value.

When using only JDBC, the mapping from tinyint(1) to boolean worked as expected:

boolean admin = resultSet.getBoolean("is_admin");

In this case, however, when using Jdbi, the getter did not fire:

The field:

@ColumnName("is_admin")
private boolean admin;

My Jdbi handler:

Jdbi jdbi = Jdbi.create(url, user, pass);
List<User> users = jdbi.withHandle(handle -> handle
            .select("select user_id, is_admin from my_db.user")
            .mapToBean(User.class)
            .list());

The solution was straightforward: Move the annotation to the getter (or setter):

@ColumnName("is_admin")
// using getAdmin() behaves the same as using isAdmin()
public boolean isAdmin() {
    return admin;
}

The documentation also mentions the following:

The @ColumnName annotation can be placed on either the getter or setter method.

But I read that as "can also be placed..." rather than "must always be placed...".

Is this the expected behavior: That you must place the annotation on a getter/setter in some specific cases  - but you can otherwise place the annotation on the field name?

Or am I making some other mistake in my approach?
- - -

I am using:

 - MySQL DB 8.0.18
 - MySQL Connector 8.0.23
 - Java 15
 - Jdbi 3.18.0

Steven Schlansker

unread,
Apr 5, 2021, 12:13:41 PM4/5/21
to jd...@googlegroups.com
You are using the "mapToBean" functionality.

A Java bean is a Java class whose properties are set by setter and getter methods -
Jdbi will *never* use the class fields when you use mapToBean.

I think you are reading the FieldMapper section of the documentation, which does reflectively find fields,
and the example in that section applies the annotation to the field, which works for FieldMapper but not Beans.

When mapping beans, always attach the ColumnName to the method, never the field.
Hope that helps,

Steven
> --
> You received this message because you are subscribed to the Google Groups "jDBI" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jdbi+uns...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/jdbi/91a726da-5390-4c5a-bb2b-0509bd4bc95dn%40googlegroups.com.

Northcoder Root

unread,
Apr 5, 2021, 2:03:43 PM4/5/21
to jd...@googlegroups.com
Understood, thank you. I was reading from different sections of the documentation.

But in that case, why does the following example work?

The MySQL table:

CREATE TABLE `test` (`user_name` varchar(10) NOT NULL, PRIMARY KEY (`user_name`));

insert into test values ('John');


The JavaBean:

import org.jdbi.v3.core.mapper.reflect.ColumnName;

public class Test {

    @ColumnName("user_name")
    private String userName;
   
    public String getUserName() {
        return userName;
    }
   
    public void setUserName(String userName) {
        this.userName = userName;
    }
   
}


The main method:

public static void main(String[] args) throws SQLException {

    String url = "jdbc:mysql://localhost:3306/x";
    String user = "y";
    String pass = "z";


    Jdbi jdbi = Jdbi.create(url, user, pass);
    List<Test> beans = jdbi.withHandle(handle -> handle
            .select("select user_name from test")
            .mapToBean(Test.class)
            .list());
    for (Test bean : beans) {
        System.out.println(bean.getUserName());
    }
}


The above code causes setUserName() to be called, and it prints the name John

How does it do this if Jdbi never uses the class fields (and therefore does not read the @ColumnName annotation) when you use mapToBean?



You received this message because you are subscribed to a topic in the Google Groups "jDBI" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jdbi/RKVrLVWla-8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jdbi+uns...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jdbi/93808016-140B-47F4-BE91-A52F6E7338FE%40gmail.com.

Northcoder Root

unread,
Apr 6, 2021, 12:58:31 PM4/6/21
to jd...@googlegroups.com
I have answered my own question, with some more research (which I should have done first, obviously).

Jdbi performs column mappings automatically, in my scenario, from snake_case column names to camelCase Java field names.

It has nothing to do with the annotation.

I never noticed before because all my DB column names were always snake-case versions of the related Java field names.


Reply all
Reply to author
Forward
0 new messages