OPENJPA-2651: Fix for issue where @SqlResultSetMapping is used with inheritance and a ManyToOne relationship. Merged 2.2.x commit to trunk.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1756047 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Heath Thomann 2016-08-11 20:43:27 +00:00
parent 41827d794d
commit 4afdb07042
5 changed files with 306 additions and 0 deletions

View File

@ -404,6 +404,20 @@ class MappedQueryResultObjectProvider
return _res.getLong((Column) obj, joins);
return _res.getLong(obj);
}
/*
* OPENJPA-2651: Added to allow the column to be translated (from the
* actual column name to the name provided in an @SqlResultSetMapping/@FieldResult.
*
* (non-Javadoc)
* @see org.apache.openjpa.jdbc.sql.AbstractResult#getObject(org.apache.
* openjpa.jdbc.schema.Column, java.lang.Object, org.apache.openjpa.jdbc.sql.Joins)
*/
public Object getObject(Column col, Object arg, Joins joins)
throws SQLException {
return getObjectInternal(translate(col, joins), col.getJavaType(),
arg, joins);
}
protected Object getObjectInternal(Object obj, int metaTypeCode,
Object arg, Joins joins)

View File

@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.query.sqlresultmapping;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
@javax.persistence.Table(name = "CRT_OPERACAO")
@Entity
public class CrtOperacaoEntity implements Serializable {
private static final long serialVersionUID = -3914425448077243671L;
@Column(name = "ID")
@Id
private long id;
public long getId() {
return this.id;
}
public void setId(final long id) {
this.id = id;
}
@Column(name = "DATA_HORA")
private Timestamp dataHora;
public Timestamp getDataHora() {
return this.dataHora;
}
public void setDataHora(final Timestamp dataHora) {
this.dataHora = dataHora;
}
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.query.sqlresultmapping;
import javax.persistence.Entity;
import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.SqlResultSetMapping;
@javax.persistence.Table(name = "CRT_REQUISICAO_CHEQUE_PERS")
@Entity
@SqlResultSetMapping(name = "MyResultMapping", entities = {
@EntityResult(entityClass = CrtRequisicaoChequePersEntity.class, fields = {
@FieldResult(name = "crtOperacaoByOperacaoRecepcaoServCent.id",
column = "opRecepcaoServCentraisId"),
@FieldResult(name = "crtOperacaoByOperacaoRecepcaoServCent.dataHora",
column = "opRecepcaoServCentraisDataHora") }) })
public class CrtRequisicaoChequePersEntity extends CrtRequisicaoEntity {
@ManyToOne
@javax.persistence.JoinColumn(name = "OPERACAO_RECEPCAO_SERV_CENT", referencedColumnName = "ID")
private CrtOperacaoEntity crtOperacaoByOperacaoRecepcaoServCent;
public CrtOperacaoEntity getCrtOperacaoByOperacaoRecepcaoServCent() {
return this.crtOperacaoByOperacaoRecepcaoServCent;
}
public void setCrtOperacaoByOperacaoRecepcaoServCent(
final CrtOperacaoEntity crtOperacaoByOperacaoRecepcaoServCent) {
this.crtOperacaoByOperacaoRecepcaoServCent =
crtOperacaoByOperacaoRecepcaoServCent;
}
@ManyToOne
@javax.persistence.JoinColumn(name = "OPERACAO_REQUISICAO", referencedColumnName = "ID", nullable = false)
private CrtOperacaoEntity crtOperacaoByOperacaoRequisicao;
public CrtOperacaoEntity getCrtOperacaoByOperacaoRequisicao() {
return this.crtOperacaoByOperacaoRequisicao;
}
public void setCrtOperacaoByOperacaoRequisicao(
final CrtOperacaoEntity crtOperacaoByOperacaoRequisicao) {
this.crtOperacaoByOperacaoRequisicao = crtOperacaoByOperacaoRequisicao;
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.query.sqlresultmapping;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.OneToOne;
@javax.persistence.Table(name = "CRT_REQUISICAO")
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class CrtRequisicaoEntity {
@Column(name = "ID")
@Id
private long id;
public long getId() {
return this.id;
}
public void setId(final long id) {
this.id = id;
}
}

View File

@ -0,0 +1,128 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.query.sqlresultmapping;
import java.sql.Timestamp;
import java.util.List;
import java.util.Properties;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import org.apache.openjpa.persistence.querycache.QCEntity;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
/*
* Test for OPENJPA-2651.
*/
public class TestSQLResultSetMapping extends SingleEMFTestCase {
public void setUp() {
super.setUp(DROP_TABLES, CrtOperacaoEntity.class,
CrtRequisicaoEntity.class, CrtRequisicaoChequePersEntity.class);
// Set up necessary test data:
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
CrtOperacaoEntity op = new CrtOperacaoEntity();
op.setId(25384);
op.setDataHora(Timestamp.valueOf("2014-12-16 15:24:54.0"));
em.persist(op);
CrtOperacaoEntity op2 = new CrtOperacaoEntity();
op2.setId(23409);
op2.setDataHora(Timestamp.valueOf("2014-10-27 16:12:53.0"));
em.persist(op2);
CrtRequisicaoChequePersEntity reqCheq =
new CrtRequisicaoChequePersEntity();
reqCheq.setId(500006164);
reqCheq.setCrtOperacaoByOperacaoRecepcaoServCent(op);
reqCheq.setCrtOperacaoByOperacaoRequisicao(op2);
em.persist(reqCheq);
em.getTransaction().commit();
em.close();
}
/*
* Prior to OPENJPA-2651, this test would result in the following exception:
*
* PersistenceException: Column '0' not found.
* FailedObject:
* org.apache.openjpa.persistence.query.sqlresultmapping.CrtOperacaoEntity-500006164 [java.lang.String]
* at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4998)
* .....
* Caused by: java.sql.SQLException: Column '0' not found.
*/
public void testMappingNoException() {
String sql = "SELECT t0.ID, t2.DATA_HORA as opRecepcaoServCentraisDataHora, t2.ID as opRecepcaoServCentraisId"
+ " FROM CRT_REQUISICAO_CHEQUE_PERS t0, CRT_OPERACAO t2 WHERE t0.ID = 500006164 and t2.ID = 25384";
EntityManager em = emf.createEntityManager();
Query query = em.createNativeQuery(sql, "MyResultMapping");
List<CrtRequisicaoChequePersEntity> res = query.getResultList();
assertEquals(res.size(), 1);
assertEquals(500006164, res.get(0).getId());
assertEquals(25384, res.get(0).getCrtOperacaoByOperacaoRecepcaoServCent().getId());
assertEquals(Timestamp.valueOf("2014-12-16 15:24:54.0"),
res.get(0).getCrtOperacaoByOperacaoRecepcaoServCent().getDataHora());
em.close();
}
/*
* Prior to OPENJPA-2651, this test would result in the wrong id provided in the
* CrtOperacaoEntity. Specifically, the ID in CrtOperacaoEntity would contain
* '500006164', which is the ID for the CrtRequisicaoEntity.
*/
public void testMappingCorrectID() {
String sql =
"SELECT t0.ID, t1.ID as opRecepcaoServCentraisId, t1.DATA_HORA as opRecepcaoServCentraisDataHora, "
+ "t2.ID, t2.DATA_HORA, t3.ID, t4.ID, t4.OPERACAO_RECEPCAO_SERV_CENT, "
+ "t4.OPERACAO_REQUISICAO FROM CRT_REQUISICAO_CHEQUE_PERS t0 LEFT OUTER JOIN "
+ "CRT_OPERACAO t1 ON t0.OPERACAO_RECEPCAO_SERV_CENT = t1.ID LEFT OUTER JOIN "
+ "CRT_OPERACAO t2 ON t0.OPERACAO_REQUISICAO = t2.ID "
+ "LEFT OUTER JOIN CRT_REQUISICAO t3 "
+ "ON t0.ID = t3.ID INNER JOIN CRT_REQUISICAO t5 "
+ "ON t0.ID = t5.ID LEFT OUTER JOIN "
+ "CRT_REQUISICAO_CHEQUE_PERS t4 "
+ "ON t3.ID = t4.ID WHERE t0.ID = 500006164";
EntityManager em = emf.createEntityManager();
Query query = em.createNativeQuery(sql, "MyResultMapping");
List<CrtRequisicaoChequePersEntity> res = query.getResultList();
assertEquals(res.size(), 1);
assertEquals(500006164, res.get(0).getId());
assertEquals(25384, res.get(0).getCrtOperacaoByOperacaoRecepcaoServCent().getId());
assertEquals(Timestamp.valueOf("2014-12-16 15:24:54.0"),
res.get(0).getCrtOperacaoByOperacaoRecepcaoServCent().getDataHora());
em.close();
}
}