[英]Getting pl/sql array of struct from stored procedure using JdbcSimpleCall
im trying to execute oracle stored procedure using SimpleJDBCCall, all tables and stored procedures are in restaurant schema, table looks like: 我试图使用SimpleJDBCCall执行oracle存储过程,所有表和存储过程都在餐厅模式中,表如下所示:
CREATE TABLE STAFF
(
STAFF_ID NUMBER(5),
STAFF_FIRST_NAME VARCHAR2(10 BYTE) NOT NULL,
STAFF_LAST_NAME VARCHAR2(20 BYTE) NOT NULL,
STAFF_ROLE VARCHAR2(20 BYTE) NOT NULL,
STAFF_OTHER_DETAILS VARCHAR2(50 BYTE)
);
my type package: 我的类型包:
CREATE OR REPLACE PACKAGE Staff_Types
AS
TYPE Staff_Collection IS TABLE OF Staff%ROWTYPE;
END Staff_Types;
my access package: 我的访问包:
CREATE OR REPLACE PACKAGE Staff_TAPI
AS
FUNCTION getAllStaff RETURN Staff_Types.Staff_Collection;
END Staff_TAPI;
CREATE OR REPLACE PACKAGE BODY Staff_Tapi
AS
FUNCTION getAllStaff
RETURN Staff_Types.Staff_Collection
IS
all_staff Staff_Types.Staff_Collection;
BEGIN
SELECT *
BULK COLLECT INTO all_staff
FROM Staff;
RETURN all_staff;
END;
END Staff_Tapi;
Java Access: Java访问:
@Component
@Qualifier("staffJdbcDAO")
public class StaffJDBCDAO implements StaffDAO {
JdbcTemplate jdbcTemplate;
SimpleJdbcCall getAllMembersSP;
@Autowired
@Qualifier("dataSource")
DataSource dataSource;
@Autowired
@Qualifier("jdbcTemplate")
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
initializeStoredProceduresCalls();
}
private void initializeStoredProceduresCalls() {
getAllMembersSP = new SimpleJdbcCall(jdbcTemplate);
getAllMembersSP.withCatalogName("Staff_Tapi");
getAllMembersSP.withFunctionName("getAllStaff");
getAllMembersSP.declareParameters(
new SqlOutParameter("return",
Types.OTHER,
"Staff_Types.Staff_Collection",
new SqlReturnStructArray<>( new StaffMapper() )
)
);
getAllMembersSP.compile();
}
@Override
public List<Staff> getAllMembers() {
Staff[] staff = getAllMembersSP.executeFunction(Staff[].class,new HashMap<String,Object>() );
return Arrays.asList(staff);
}
}
mapping class: 映射类:
public class StaffMapper implements StructMapper<Staff> {
@Override
public STRUCT toStruct(Staff staff, Connection connection, String typeName) throws SQLException {
StructDescriptor descriptor = StructDescriptor.createDescriptor(typeName, connection);
Object[] attributes = new Object[5];
attributes[0] = new Integer( staff.getId() );
attributes[1] = new String("STAFF_FIRST_NAME");
attributes[2] = new String("STAFF_LAST_NAME");
attributes[3] = new String("STAFF_ROLE");
attributes[4] = new String("STAFF_OTHER_DETAILS");
Struct staffStruct = connection.createStruct(typeName,attributes);
return new STRUCT(descriptor,connection,attributes);
}
@Override
public Staff fromStruct(STRUCT struct) throws SQLException {
StructDescriptor descriptor = struct.getDescriptor();
ResultSetMetaData metaData = descriptor.getMetaData();
Object[] attributes = struct.getAttributes();
Map<String,Object> attributeMap = new HashMap<>();
int idx = 1;
for ( Object attribute : attributes )
attributeMap.put( metaData.getColumnName(idx++),attribute );
int id = ((Integer)attributeMap.get("STAFF_ID")).intValue();
String firstName = (String) attributeMap.get("STAFF_FIRST_NAME");
String lastName = (String) attributeMap.get("STAFF_LAST_NAME");
String staffRole = (String) attributeMap.get("STAFF_ROLE");
String otherDetails = (String) attributeMap.get("STAFF_OTHER_DETAILS");
return new Staff(id,firstName,lastName,staffRole,otherDetails);
}
}
and staff: 和员工:
public class Staff {
private int id;
private String firstName;
private String lastName;
private String profession;
private String otherDetails;
public Staff(int id, String firstName, String lastName, String profession, String otherDetails) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.profession = profession;
this.otherDetails = otherDetails;
}
public int getId() {
return id;
}
public int setId(int id) {
this.id = id;
}
// and others getters and setters
}
when i execute getAllMembers from StaffDAO im constatly getting : CallableStatementCallback; 当我从StaffDAO执行getAllMembers时,即时获得:CallableStatementCallback; uncategorized SQLException for SQL [{? 未分类的SQLException for SQL [{? = call STAFF_TAPI.GETALLSTAFF()}]; =呼叫STAFF_TAPI.GETALLSTAFF()}]; SQL state [99999]; SQL状态[99999]; error code [17004]; 错误代码[17004]; Invalid column type: 1111; 无效的列类型:1111;
when i change return type parameter to Types.Array i get: CallableStatementCallback; 当我将返回类型参数更改为Types.Array时,我得到:CallableStatementCallback; uncategorized SQLException for SQL [{? 未分类的SQLException for SQL [{? = call STAFF_TAPI.GETALLSTAFF()}]; =呼叫STAFF_TAPI.GETALLSTAFF()}]; SQL state [99999]; SQL状态[99999]; error code [17074]; 错误代码[17074];
invalid name pattern: restaurant.Staff_Types.Staff_Collection; 无效的名称模式:restaurant.Staff_Types.Staff_Collection;
i tried in both ways with pattern "Staff_Types.Staf_collection" getting same results, im trying to do this for nearly 2 days without any idea what should i do, if anyone has any suggestions i will be greateful. 我以两种方式尝试了“ Staff_Types.Staf_collection”模式,得到了相同的结果,即时通讯试图将近2天不知道该怎么办,如果有人有任何建议,我将不胜感激。
In order to easily integrate your PL/SQL call, and since it is already built as a function: have you thought about something like this? 为了轻松集成您的PL / SQL调用,并且它已经作为函数构建,您是否考虑过类似的事情?
select * from TABLE(CAST(Staff_Tapi.getAllStaff() as Staff_Types.Staff_Collection))
This way, you can execute it easily as a regular JDBC query. 这样,您可以轻松地将其作为常规JDBC查询执行。 Once done, just process the ResultSet
it returns with some minor variant of your fromStruct
method in order to return a List<Staff>
list to whatever business logic you have on top of it. 完成后,只需处理ResultSet
并使用fromStruct
方法的一些较小变体即可返回ResultSet
,以便将List<Staff>
列表返回到其之上的任何业务逻辑。 Hope you find this useful! 希望你觉得这个有用!
You cannot load a PL/SQL record
from a stored procedure through JDBC. 您不能通过JDBC从存储过程中加载PL / SQL record
。 In fact, you cannot even load such a type from Oracle SQL. 实际上,您甚至无法从Oracle SQL加载此类。 See also this question for details: 另请参阅此问题以获取详细信息:
You can only load SQL types through JDBC (as opposed to PL/SQL types). 您只能通过JDBC加载SQL类型(与PL / SQL类型相反)。 Given your example, you'll need to write: 给定您的示例,您需要编写:
-- You cannot really avoid this redundancy
CREATE TYPE STAFF AS OBJECT
(
STAFF_ID NUMBER(5),
STAFF_FIRST_NAME VARCHAR2(10 BYTE) NOT NULL,
STAFF_LAST_NAME VARCHAR2(20 BYTE) NOT NULL,
STAFF_ROLE VARCHAR2(20 BYTE) NOT NULL,
STAFF_OTHER_DETAILS VARCHAR2(50 BYTE)
);
CREATE TYPE STAFF_TABLE AS TABLE OF STAFF;
And then: 接着:
CREATE OR REPLACE PACKAGE Staff_TAPI
AS
FUNCTION getAllStaff RETURN STAFF_TABLE;
END Staff_TAPI;
You may want to capitalize your custom type in java code like 您可能需要在Java代码中使用大写的自定义类型,例如
getAllMembersSP.declareParameters(
new SqlOutParameter("return",
Types.OTHER,
"STAFF_TYPES.STAFF_COLLECTION",
new SqlReturnStructArray<>( new StaffMapper() )
)
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.