I am converting a legacy application to a Spring Boot, Groovy, JPA solution and found myself with a query in the form of:
SELECT ...
FROM table1, table2
WHERE table1.field1 = table2.field1 AND
table1.field2 = table2.field2 and
table2.field3 = 'ABC'
As you can see, the join is perform on three fields, 2 of them that are based on data from table1 and a third field that is a constant string.
So, for what I googled around (i.e. http://docs.oracle.com/cd/E13189_01/kodo/docs40/full/html/ref_guide_mapping_notes_nonstdjoins.html ) I found that a solution would be:
@Entity
@Table(name = "Table1")
class Table1 {
// other column definitions here
@OneToOne(cascade = CascadeType.ALL)
@JoinColumns([
@JoinColumn(name="field1", referencedColumnName="field1"),
@JoinColumn(name="field2", referencedColumnName="field2"),
@JoinColumn(name="table2.field3", referencedColumnName="'ABC'")]
)
Table2 table2
}
When I run this I am getting a "Unable to find column with logical name: 'ABC' in table2" exception:
Caused by: org.hibernate.MappingException: Unable to find column with logical name: 'ABC' in table2
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:854) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:241) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:100) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1786) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1730) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1617) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) ~[hibernate-entitymanager-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) ~[hibernate-entitymanager-5.0.9.Final.jar:5.0.9.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.2.RELEASE.jar:4.3.2.RELEASE]
However this solution only seems to work with a @OneToMany relationship, as pointed by the referred example.
I am trying to connect to a legacy Informix database for which changing the schema is completely out of the question. In addition to that, my build.gradle looks like this (the relevant portion anyways):
buildscript {
repositories {
// ...
}
dependencies { classpath('org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE') }
}
apply plugin: 'groovy'
apply plugin: 'spring-boot'
defaultTasks 'clean', 'assemble'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
// ...
}
dependencies {
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "org.springframework:spring-jms"
compile "org.apache.cxf:cxf-rt-frontend-jaxws:${cxfVersion}"
compile "org.apache.cxf:cxf-rt-transports-http:${cxfVersion}"
compile "org.codehaus.groovy:groovy-all:2.4.4"
compile "informix:informix-jdbc:${informixVersion}"
compile "informix:informix-jdbcx:${informixVersion}"
testCompile "org.springframework.boot:spring-boot-starter-test"
testCompile "org.spockframework:spock-core:${spockVersion}"
testCompile "org.spockframework:spock-spring:${spockVersion}"
testCompile "junit:junit:4.12"
testCompile "org.springframework:spring-test"
}
Has anyone run into a problem like this? Or what would be the correct approach to address situations like this?
Thanks a lot in advance for your help