gpt4 book ai didi

java - 从 SP 到复杂对象的映射结果

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:21:55 27 4
gpt4 key购买 nike

我正在尝试在我的工作项目中实现 MyBatis。它是一个遗留系统,仅通过存储过程使用普通 JDBC 访问数据库。我知道要调用存储过程,MyBatis 需要一个包含存储过程输入参数的对象和另一个保存结果集的对象。不确定这是否完全正确。

为了防止在系统中创建过多的数据实体,我想重用现有的。这就是问题所在。让我解释一下我面临的典型情况/场景,然后我将如何解决它。

假设我在系统中有以下数据实体:

class Account {
private int accountID;
private String accountName;
private OrganizationAddress address;
// Getters-Setters Go Here
}
class OrganizationAddress extends Address {
// ... some attributes here
// Getters-Setters Go Here
}
class Address {
private String address;
private String city;
private String state;
private String country;
// Getters-Setters Go Here
}

我正在使用注解,所以我的 Mapper 类有这样的东西:

@Select(value = "{call Get_AccountList(#{accountType, mode=IN, jdbcType=String})}")
@Options(statementType = StatementType.CALLABLE)
@Results(value = {
@org.apache.ibatis.annotations.Result
(property = "accountID", column = "Account_ID"),
@org.apache.ibatis.annotations.Result
(property = "accountName", column = "Organization_Name"),
@org.apache.ibatis.annotations.Result
(property = "state", column = "State", javaType=OrganizationAddress.class)
})
List<Account> getAccountList(Param param);

问题:当我调用存储过程时,Account 对象的state 总是null.

雪上加霜的是,我无法访问上述数据实体的来源。所以我也无法尝试此链接上提供的解决方案 - Mybatis select with nested objects

我的查询:

  • 我是否可以使用系统中已有的数据实体,还是必须创建新的数据实体,然后将数据映射到现有的数据实体?
    • 如果是,我该怎么做?任何引用资料(如果有)。
    • 如果不是,是否有办法减少我为调用存储过程(输入和输出参数)而创建的数据实体的数量?

最佳答案

我认为针对您的情况的最佳解决方案(如果我理解正确的话)是使用 MyBatis TypeHandler 将状态列映射到 OrganizationAddress 对象。

我已经根据您提供的信息整理了一个示例,并且可以正常工作。这是修改后的注释映射器:

// Note: you have an error in the @Select line => maps to VARCHAR not "String"
@Select(value = "{call Get_AccountList(#{accountType, mode=IN, jdbcType=VARCHAR})}")
@Options(statementType = StatementType.CALLABLE)
@Results(value = {
@org.apache.ibatis.annotations.Result
(property = "accountID", column = "Account_ID"),
@org.apache.ibatis.annotations.Result
(property = "accountName", column = "Organization_Name"),
@org.apache.ibatis.annotations.Result
(property = "address", column = "State", typeHandler=OrgAddressTypeHandler.class)
})
List<Account> getAccountList(Param param);

您需要将 Account 的地址字段映射到“state”列,并使用 TypeHandler 创建一个填充了“state”属性的 OrganizationAddress。

我创建的 OrgAddressTypeHandler 如下所示:

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

public class OrgAddressTypeHandler extends BaseTypeHandler<OrganizationAddress> {

@Override
public OrganizationAddress getNullableResult(ResultSet rs, String colName) throws SQLException {
OrganizationAddress oa = new OrganizationAddress();
oa.setState(rs.getString(colName));
return oa;
}

@Override
public OrganizationAddress getNullableResult(ResultSet rs, int colNum) throws SQLException {
OrganizationAddress oa = new OrganizationAddress();
oa.setState(rs.getString(colNum));
return oa;
}

@Override
public OrganizationAddress getNullableResult(CallableStatement cs, int colNum) throws SQLException {
OrganizationAddress oa = new OrganizationAddress();
oa.setState(cs.getString(colNum));
return oa;
}

@Override
public void setNonNullParameter(PreparedStatement arg0, int arg1, OrganizationAddress arg2, JdbcType arg3) throws SQLException {
// not needed for this example
}
}

如果您需要比这更完整的工作示例,我很乐意发送更多示例。或者,如果我误解了您的示例,请告诉我。

通过此解决方案,您可以在不修改的情况下使用您的域对象。您只需要 TypeHandler 来执行映射,而不需要 XML 映射器文件。

我也在 MySQL 中用 MyBatis-3.1.1 做了这个。这是我为测试它而创建的简单架构和存储过程:

DROP TABLE IF EXISTS account;
DROP TABLE IF EXISTS organization_address;

CREATE TABLE account (
account_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
organization_name VARCHAR(45) NOT NULL,
account_type VARCHAR(10) NOT NULL,
organization_address_id SMALLINT UNSIGNED NOT NULL,
PRIMARY KEY (account_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE organization_address (
organization_address_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
address VARCHAR(45) NOT NULL,
city VARCHAR(45) NOT NULL,
state VARCHAR(45) NOT NULL,
country VARCHAR(45) NOT NULL,
PRIMARY KEY (organization_address_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO organization_address VALUES(1, '123 Foo St.', 'Foo City', 'Texas', 'USA');
INSERT INTO organization_address VALUES(2, '456 Bar St.', 'Bar City', 'Arizona', 'USA');
INSERT INTO organization_address VALUES(3, '789 Quux Ave.', 'Quux City', 'New Mexico', 'USA');

INSERT INTO account VALUES(1, 'Foo', 'Type1', 1);
INSERT INTO account VALUES(2, 'Bar', 'Type1', 2);
INSERT INTO account VALUES(3, 'Quux', 'Type2', 3);

DROP PROCEDURE IF EXISTS Get_AccountList;

DELIMITER $$

CREATE PROCEDURE Get_AccountList(IN p_account_type VARCHAR(10))
READS SQL DATA
BEGIN
SELECT a.account_id, a.organization_name, o.state
FROM account a
JOIN organization_address o ON a.organization_address_id = o.organization_address_id
WHERE account_type = p_account_type
ORDER BY a.account_id;
END $$

DELIMITER ;

关于java - 从 SP 到复杂对象的映射结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11156713/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com