i'm trying to call a stored procedure with few parameter and one of them is a VARRAY of an OBJECT in Oracle DB. But i think the problem is with the parameters OUT. I'm using MyBatis.
This is the procedure:
procedure pr_log_admin(IN_nome_procedura in varchar2,
IN_id_utente in number,
IN_id_record in varchar2,
IN_nome_tabella in varchar2,
IN_altri_campi in V_ELENCO_CAMPI_MODIFICATI,
err_text out varchar2,
err_code out number)
This the types:
create or replace TYPE "V_ELENCO_CAMPI_MODIFICATI" as varray(200) of ty_campi_modificati;
create or replace TYPE "TY_CAMPI_MODIFICATI" AS OBJECT (
nome_campo varchar2(100),
valore_old varchar2(100),
valore_new varchar2(100)
);
Here the mapper:
<select id="log" statementType="CALLABLE"
parameterType="com.ubiss.domain.logger.LoggedElement"
resultMap="loggedResult">
{call dynapp.pkg_log_admin.pr_log_admin(
#{nomeProcedura, mode=IN, jdbcType=VARCHAR},
#{idUser, mode=IN, jdbcType=NUMERIC},
#{idRecord, mode=IN, jdbcType=VARCHAR},
#{nomeTabella, mode=IN, jdbcType=VARCHAR},
#{altriCampi, mode=IN, jdbcType=ARRAY},
#{errText,jdbcType=VARCHAR, javaType=java.lang.String, mode=OUT},
#{errCode,jdbcType=NUMERIC, javaType=java.lang.Long, mode=OUT}
)}
</select>
<resultMap id="loggedResult"
type="com.ubiss.domain.logger.LoggedElement">
<id column="IN_nome_procedura" property="nomeProcedura" />
<id column="IN_id_utente" property="idUtente" />
<id column="IN_id_record" property="idRecord" />
<id column="IN_nome_tabella" property="nomeTabella" />
<id column="IN_altri_campi" property="altriCampi" typeHandler="com.ubiss.domain.logger.ElencoCampiTypeHandler" />
<id column="err_text" property="errText" />
<id column="err_code" property="errCode" />
</resultMap>
Here Java classes:
public interface LoggerDao {
public LoggedElement log(LoggedElement elementLogged);
}
package com.ubiss.domain.logger;
import com.ubiss.domain.BaseSpResult;
public class LoggedElement extends BaseSpResult{
private static final long serialVersionUID = 1L;
private String nomeProcedura;
private Long idUser;
private String idRecord;
private String nomeTabella;
private ElencoCampiModificati altriCampi;
public LoggedElement() {}
public LoggedElement(String nomeProcedura, Long idUser, String idRecord, String nomeTabella,
ElencoCampiModificati altriCampi) {
super();
this.nomeProcedura = nomeProcedura;
this.idUser = idUser;
this.idRecord = idRecord;
this.nomeTabella = nomeTabella;
this.altriCampi = altriCampi;
}
public String getNomeProcedura() {
return nomeProcedura;
}
public void setNomeProcedura(String nomeProcedura) {
this.nomeProcedura = nomeProcedura;
}
public Long getIdUser() {
return idUser;
}
public void setIdUser(Long idUser) {
this.idUser = idUser;
}
public String getIdRecord() {
return idRecord;
}
public void setIdRecord(String idRecord) {
this.idRecord = idRecord;
}
public String getNomeTabella() {
return nomeTabella;
}
public void setNomeTabella(String nomeTabella) {
this.nomeTabella = nomeTabella;
}
public ElencoCampiModificati getAltriCampi() {
return altriCampi;
}
public void setAltriCampi(ElencoCampiModificati altriCampi) {
this.altriCampi = altriCampi;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
package com.ubiss.domain;
import java.io.Serializable;
public class BaseSpResult implements Serializable {
private static final long serialVersionUID = 1L;
protected Long errCode;
protected String errText;
public Long getErrCode() {
return errCode;
}
public void setErrCode(Long errCode) {
this.errCode = errCode;
}
public String getErrText() {
return errText;
}
public void setErrText(String errText) {
this.errText = errText;
}
public boolean isOk() {
return (errCode == null) || (errCode == 0);
}
/**
* Builds an error description using errCode: errText Deprecated: Use
* {@link buildDescription()} instead
*
* @return
*/
@Deprecated()
public String buildErrorDescription() {
String errMsg = "";
if (!isOk()) {
errMsg = errCode.toString();
if (!"".equals(errText) && errText != null) {
errMsg = errMsg + ": " + errText;
}
}
return errMsg;
}
/**
* Builds a return description message using errCode: errText. Note that errCode and errText will also carry success code and text.
* @return
*/
public String buildDescription() {
String errMsg = "";
if (errCode != null) {
errMsg = errCode.toString();
if (!"".equals(errText) && errText != null) {
errMsg = errMsg + ": " + errText;
}
}
return errMsg;
}
public void cleanReturnCode() {
errCode = null;
errText = null;
}
public void buildGenericError() {
errCode = -1L;
errText = "Errore generico";
}
public String toStatusString() {
return "{errCode: " + errCode + ", errText: " + errText + "}";
}
}
package com.ubiss.domain.logger;
import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Map;
public class ElencoCampiModificati implements Array{
private CampoModificato[] campiModificati;
public ElencoCampiModificati() {}
public ElencoCampiModificati(CampoModificato[] campiModificati) {
this.campiModificati = campiModificati;
}
public CampoModificato[] getCampiModificati() {
return campiModificati;
}
public void setCampiModificati(CampoModificato[] campiModificati) {
this.campiModificati = campiModificati;
}
@Override
public String getBaseTypeName() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public int getBaseType() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
@Override
public Object getArray() throws SQLException {
// TODO Auto-generated method stub
return campiModificati == null ? null : Arrays.copyOf(campiModificati, campiModificati.length);
}
@Override
public Object getArray(Map<String, Class<?>> map) throws SQLException {
// TODO Auto-generated method stub
return this.getArray();
}
@Override
public Object getArray(long index, int count) throws SQLException {
// TODO Auto-generated method stub
return campiModificati == null ? null : Arrays.copyOfRange(campiModificati, (int)index, (int)index + count );
}
@Override
public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException {
// TODO Auto-generated method stub
return this.getArray(index, count);
}
@Override
public ResultSet getResultSet() throws SQLException {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
@Override
public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
@Override
public ResultSet getResultSet(long index, int count) throws SQLException {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
@Override
public ResultSet getResultSet(long index, int count, Map<String, Class<?>> map) throws SQLException {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
@Override
public void free() throws SQLException {
// TODO Auto-generated method stub
}
}
package com.ubiss.domain.logger;
import java.io.Serializable;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
public class CampoModificato implements SQLData, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String nome_campo;
private String valore_old;
private String valore_new;
public CampoModificato() {}
public CampoModificato(String nome_campo, String valore_old, String valore_new) {
this.nome_campo = nome_campo;
this.valore_old = valore_old;
this.valore_new = valore_new;
}
public String getNomeCampo() {
return nome_campo;
}
public void setNomeCampo(String nome_campo) {
this.nome_campo = nome_campo;
}
public String getValoreOld() {
return valore_old;
}
public void setValoreOld(String valore_old) {
this.valore_old = valore_old;
}
public String getValoreNew() {
return valore_new;
}
public void setValoreNew(String valore_new) {
this.valore_new = valore_new;
}
@Override
public String getSQLTypeName() throws SQLException {
// TODO Auto-generated method stub
return "TY_CAMPI_MODIFICATI";
}
@Override
public void readSQL(SQLInput stream, String typeName) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public void writeSQL(SQLOutput stream) throws SQLException {
// TODO Auto-generated method stub
}
}
package com.ubiss.domain.logger;
import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import oracle.jdbc.driver.OracleConnection;
public class ElencoCampiTypeHandler implements TypeHandler<ElencoCampiModificati>{
@Override
public void setParameter(PreparedStatement ps, int i, ElencoCampiModificati parameter, JdbcType jdbcType)
throws SQLException {
// TODO Auto-generated method stub
Object[] values = Arrays.stream(parameter.getCampiModificati()).toArray();
Array arr = ps.getConnection().unwrap(OracleConnection.class).createARRAY("V_ELENCO_CAMPI_MODIFICATI", values);
ps.setArray(i, arr);
}
@Override
public ElencoCampiModificati getResult(ResultSet rs, String columnName) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public ElencoCampiModificati getResult(ResultSet rs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public ElencoCampiModificati getResult(CallableStatement cs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
return null;
}
}
This is the call:
String procedura = "director_man.PKG_ANAG_CLIENTI.pr_AnagCensisci ---> parameters: ";
procedura.concat("doTrigger=" + res.getDoTrigger() + " - ");
procedura.concat("doMigra=" + res.getDoMigra() + " - ");
procedura.concat("doInit=" + res.getDoInit() + " - ");
procedura.concat("doPulisci=" + res.getDoPulisci() + " - ");
procedura.concat("ndgCoi=" + res.getNdgCoi());
CampoModificato mod = new CampoModificato("","","");
CampoModificato[] arr = new CampoModificato[] {mod};
ElencoCampiModificati elenco = new ElencoCampiModificati(arr);
LoggedElement logElement = new LoggedElement(procedura, Long.valueOf(1), "", "", elenco);
loggerDao.log(logElement);
This is the error:
Caused by: Error : 6550, Position : 6, Sql = BEGIN dynapp.pkg_log_admin.pr_log_admin(
:1 ,
:2 ,
:3 ,
:4 ,
:5 ,
:6 ,
:7
); END;, OriginalSql = {call dynapp.pkg_log_admin.pr_log_admin(
?,
?,
?,
?,
?,
?,
?
)}, Error Msg = ORA-06550: riga 1, colonna 7:
I tried to check the names of the parameters and their order to not differ between code and db side