Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Column types in child entities, specified via AttributeOverrides, are ignored #567

Open
mmoayyed opened this issue Feb 3, 2023 · 5 comments
Assignees

Comments

@mmoayyed
Copy link

mmoayyed commented Feb 3, 2023

Using the latest version of com.vladmihalcea:hibernate-types-60:2.21.1, I have run into a strange scenario with Oracle-XE.

Suppose there is this entity class:

public class BaseEntity {
    @Type(JsonType.class)
    @Column(columnDefinition = "json")
    private Map<String, List<Object>> attributes;
}

Then a child entity:

@AttributeOverrides(@AttributeOverride(name = "attributes",
    column = @Column(columnDefinition = "varchar2(4000 char)")))
public class MyEntity extends BaseEntity {
}

The type parameter that is resolved for MyEntity is always json; not varchar2.

This happens here:

if (this.dialect instanceof OracleDialect) {
    if (this.properties != null) {
        DynamicParameterizedType.ParameterType parameterType = ParameterTypeUtils.resolve(this.properties);
        if (parameterType != null) {
            String columnType = ParameterTypeUtils.getColumnType(parameterType); // possible problem? 
            if (!StringUtils.isBlank(columnType)) {
                switch (columnType) {
                    case "json":
                        return JsonBytesJdbcTypeDescriptor.of(Database.ORACLE);
                    case "blob":
                    case "clob":
                        return JsonBlobJdbcTypeDescriptor.INSTANCE;
                    case "varchar2":
                    case "nvarchar2":
                        return JsonStringJdbcTypeDescriptor.INSTANCE;
                }
            }
        }
    }

    if (metaDataInfo.getDatabaseMajorVersion() >= 21) {
        return JsonBytesJdbcTypeDescriptor.of(Database.ORACLE);
    }
}

As it appears, column types do not consider overrides:

    public static String getColumnType(DynamicParameterizedType.ParameterType parameterType) {
        if (parameterType != null) {
            Column columnAnnotation = (Column)getAnnotationOrNull(parameterType, Column.class);
            if (columnAnnotation != null) {
                String columnDefinition = columnAnnotation.columnDefinition();
                if (!StringUtils.isBlank(columnDefinition)) {
                    Matcher matcher = COLUMN_TYPE_PATTERN.matcher(columnDefinition);
                    if (matcher.matches()) {
                        return StringUtils.toLowercase(matcher.group(1));
                    }
                }
            }
        }

        return null;
    }

I don't know if this is really me doing strange things, or whether this is in fact something that could be supported, but figured you likely may want to review.

(If I do not use varchar2 or nvarchar2 as the override type, the value in the DB is stored as HEX, and then cannot be used for querying, etc. I think this project also has issues decoding the hex value back to JSON).

@vladmihalcea
Copy link
Owner

vladmihalcea commented Feb 3, 2023

Using the latest version of com.vladmihalcea:hibernate-types-60:2.21.1, I have run into a strange scenario with Oracle-XE.

You're not using the latest version. In fact, you're using the 2.x branch that's no longer supported. You will have to upgrade to version 3.x to benefit from the latest features that will be added.

The type parameter that is resolved for MyEntity is always json; not varchar2.

The GenericOracleJsonTypeVarcharPropertyTest shows you how to use the JsonType in Oracle with a VARCHAR column:

@Type(JsonType.class)
@Column(columnDefinition = "VARCHAR2(1000)")
private String properties;

Why are you using both the columnDefinition = "json" only to override it with @AttributeOverride?

The @AttributeOverride is not currently supported. If this is needed for your project, you should investigate how to add support for it.

@mmoayyed
Copy link
Author

mmoayyed commented Feb 3, 2023

Sounds good, thank you. I'll switch to the really-latest version and research this a bit more :)

Why are you using both the columnDefinition = "json" only to override it with @AttributeOverride?

In this example, I have a base entity that captures common settings. Then, I have 4-5 other child entities for each specific database type. So in reality, it would be:

public class BaseEntity {
    @Type(JsonType.class)
    @Column(columnDefinition = "json")
    private Map<String, List<Object>> attributes;
}

Then:

public class OracleEntity extends BaseEntity {
}

public class MySQLEntity extends BaseEntity {
}

The attribute-override is a strategy here to override stuff in the parent entity. For example, I can make MySQL work with @Column(columnDefinition = "json"), however, this does not work with Oracle. If I do work out support for @AttributeOverride, I suppose this would be something I can submit via a PR?

@vladmihalcea
Copy link
Owner

If you can find a way to fix it, then send a Pull Request with the change proposal.

@mmoayyed
Copy link
Author

mmoayyed commented Feb 3, 2023

Sweet, thank you! Should I close out this issue, or would you prefer to keep this open?

@vladmihalcea
Copy link
Owner

Why close it if you want to fix it? Usually, an issue is closed when it's done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants