Envers + MYSQL + List = SQLSyntaxErrorExce

2019-08-31 01:57发布

I am extending an existing application with Audit support using Envers. I annotated all @Entity classes and I got a bunch of Exception traces. When taking a look at them, it seems that they all relate to attribute definitions that have the following form

protected List<String> testActivities;  

@ElementCollection
protected List<String> getTestActivities() {
    return testActivities;
}

public void setTestActivities(List<String> testActivities) {
    this.testActivities = FXCollections.observableList(testActivities);
}

All exceptions are List<String> attributes, and the getter method has a @ElementCollection annotation.

The Exception I am getting is always (here is the exception for the above testActivities attribute)

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table TestCase_testActivities_AUD (REV integer not null, TestCase_id bigint not null, testActivities varchar(255) not null, REVTYPE tinyint, primary key (REV, TestCase_id, testActivities)) engine=MyISAM" via JDBC Statement
..
Caused by: java.sql.SQLSyntaxErrorException: Specified key was too long; max key length is 1000 bytes
..

I guess the issue is the primary key containing the testActivities?!

The testActivities attribute refers to a list of instructions that a user has to perform, so reducing the String length on the code side, as suggested on some StackOverflow pages related to the key length issue, is probably not an option?!

Currently all tables are created with DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci and I could probably save memory by using utf8 instead of utf8mb4, but is that a good and reliable solution?

How to fix this the right way? I am open to different views regarding the above two points.

I run MySQL Server 8.0.15, MyISAM, and
I am using Spring Boot which gives me Hibernate Envers 5.3.10

1条回答
Deceive 欺骗
2楼-- · 2019-08-31 02:50

I forgot to mention that I am using @Access(AccessType.PROPERTY)on the class level. Anyway, I extended the related getter methods

@ElementCollection  
@Column(length=175)     // keep in sync with maxDBStringLength
public List<String> getEnvironmentalInterfaces() {
    return environmentalInterfaces;
}

Thus actually does the trick. However, in order to not loose information, I also extended all methods to add an element to the list, like so

// Must be in sync with @Column(length=175)  definitions
protected static int maxDBStringLength = Constants.maxDBStringLength;

public void addEnvironmentalInterfaces(String environmentalInterface) throws StringTooLongException {
    if(environmentalInterface.length() > maxDBStringLength) {
        throw new StringTooLongException(maxDBStringLength, environmentalInterface.length());
    }
    environmentalInterfaces.add(environmentalInterface);
}

Now all tables are created. Unfortunately I have now a NullPointer issue, which you find here Envers NullPointerException when creating test data - just in case you are going through the same learning curve.

查看更多
登录 后发表回答