Provided id of the wrong type - Spring

Viewed 97

I struggle with this problem for few days and I hope you are able to help me solve it. Maybe I made something wrong with generic types, but maybe it's some unpredictable behaviour of Spring.

Situation is very strange because I found out that application works differently when I use autoconfigure or when I configure entity manager myself. In both cases it doesn’t work correctly but once I get exception when I try to fetch entity from database:

org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.example.repoinherit.model.DocTwo. Expected: class com.example.repoinherit.model.DocOneId, got class com.example.repoinherit.model.DocTwoId

and in the second case it just don’t find entity with specific ID in database. In both cases saving data works OK and all data are in databases.

Which case it is depends on how I configure database connection. If I use autoconfigure I get exception, if I have custom entity manager I cant find entity. Unfortunately yesterday it was working completely opposite – It’s probably related with next “funny” fact.

I have 3 entities but problem is always with only one of them. What is even more interesting it depends on their names. When I change class name it probably change theirs orders and another class stop working.

Bellow you can find excerpt from code. I prepared also test project which you can find here https://gitlab.com/pin54/springproblem.git Instead of tests there is a "real" controller

Each entity (DocOne, DocTwo, DocThree) is derived class of Document which is derived class of AggregateRoot. All of them looks almost the same, so bellow you can find only one implementation. ID of each entity (DocOneId, DocTwoId, DocThreeId) is derived class of AggregateId

Thank you in advance for your support.

@MappedSuperclass
public abstract class AggregateRoot<ID extends AggregateId> {

    @EmbeddedId
    @Type(type = "org.hibernate.type.UUIDCharType")
    protected ID id;

    public AggregateRoot(ID id) {
        this.id = id;
    }

    public AggregateRoot() {

    }
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", columnDefinition = "varchar(10)")
@Table(name = "documents")
public abstract class Document<ID extends AggregateId> extends AggregateRoot<ID> {

    protected String number;

    public Document(ID id) {
        super(id);
    }

    public Document() {

    }
}
@Entity
@DiscriminatorValue("one")
public class DocOne extends Document<DocOneId> {

    public String docOneField;

    public DocOne(DocOneId id) {
        super(id);
        docOneField = "one";
    }

    public DocOne() {

    }
}
@Embeddable
@MappedSuperclass
public class DocOneId extends AggregateId {

    public DocOneId(String id) { super(id); }

    public DocOneId(UUID id) { super(id); }

    public DocOneId() {

    }
}
@Repository
public interface DocOneRepository extends JpaRepository<DocOne, DocOneId> {

}
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = {
                "com.example.repoinherit.model"
        },
        entityManagerFactoryRef = "productionEntityManagerFactory",
        transactionManagerRef= "productionTransactionManager"
)
public class DatabaseConfigurationProduction {

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.production")
    public DataSourceProperties productionDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.spring.jpa.production")
    public Map<String, String> productionJpaProperties() {
        return new HashMap<>();
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.production.configuration")
    public DataSource productionDataSource() {
        return productionDataSourceProperties().initializeDataSourceBuilder()
                .type(HikariDataSource.class).build();
    }

    @Bean(name = "productionEntityManagerFactory")
    @Primary
    public LocalContainerEntityManagerFactoryBean productionEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        System.out.println(productionJpaProperties());
        return builder
                .dataSource(productionDataSource())
                .packages(new String[] {
                        "com.example.repoinherit.model"
                })
                .properties(productionJpaProperties())
                .build();
    }

    @Primary
    @Bean
    public PlatformTransactionManager productionTransactionManager(
            final @Qualifier("productionEntityManagerFactory") LocalContainerEntityManagerFactoryBean productionEntityManagerFactory) {
        return new JpaTransactionManager(productionEntityManagerFactory.getObject());
    }

}

EDIT: Probably I made mistake when I wrote that in one case it cant find entity - it can. So, it works correctly when I have config for entity manager and throw an exception when I do not use it. But in second project it throw exception when I use config for entity manager (the same config!).

0 Answers
Related