MyBatis return 是一个 List 并且不想 return 一个对象
MyBatis returns a List and doesn't want to return an object
我想使用 MyBatis 3 从 PostgreSQL 数据库中检索数据。
我在界面上写了这个映射器:
package datamodel.gis.building;
public interface BuildingMapperBatis
{
// List of objects within rectangular box
public List<BuildingDbDto> getByBBox( @Param("lat1") BigDecimal lat1,
@Param("lon1") BigDecimal lon1,
@Param("lat2") BigDecimal lat2,
@Param("lon2") BigDecimal lon2 );
// Retrieve the object by id
public BuildingDbDto getById( @Param("id") Long id );
/// public List<BuildingDbDto> getById( @Param("id") Long id );
}
class BuildingDbDto 是一个普通的 DTO 对象,具有私有字段、public getter、没有 setter 和一个初始化所有字段的构造函数。
一块MyBatis XML配置是:
<configuration>
<typeAliases>
<typeAlias alias="Building" type="datamodel.gis.building.BuildingDbDto" />
</typeAliases>
<environments default="default">...here is the connection specified...</environments>
<mappers>
<mapper resource="datamodel/gis/building/BuildingMapperBatis.xml" />
</mappers>
</configuration>
文件“/src/main/resources/datamodel/gis/building/BuildingMapperBatis.xml”中mapper的XML配置为:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="datamodel.gis.building.BuildingMapperBatis">
<resultMap id="BuildingMap" type="Building" >
<id column="bld_id" property="id" />
<result column="bld_geo_latitude" property="latitude" />
<result column="bld_geo_longitude" property="longitude" />
<result column="bld_addr_settlement_name" property="addrSettlementName" />
</resultMap>
<select id="getByBBox" resultMap="BuildingMap">
SELECT bld_id, bld_geo_latitude, bld_geo_longitude, bld_addr_settlement_name
FROM get_buildings_in_bbox( #{lat1}, #{lon1}, #{lat2}, #{lon2} )
</select>
<!-- <select id="getById" resultMap="Building"> -->
<select id="getById" resultType="Building">
SELECT bld_id, bld_geo_latitude, bld_geo_longitude, bld_addr_settlement_name
FROM get_buildings_in_bbox( 0,0,90,90)
WHERE bld_id = #{id}
</select>
</mapper>
然后我执行查询:
BuildingMapperBatis mapper = sessionFactory.openSession().getMapper( BuildingMapperBatis.class );
List<BuildingDbDto> found = mapper.getByBBox( lat1, lon1, lat2, lon2 );
BuildingDbDto dto = mapper.getById( id );
/*///
BuildingDbDto dto = mapper.getById( id ).get(0);
*/
getByBBox 方法确实有效。
getById 方法在“.getById( id );”行抛出异常:
“java.lang.IllegalAccessError:试图从 class com.sun.proxy 访问 class datamodel.gis.building.BuildingDbDto。$Proxy0
在 com.sun.proxy.$Proxy0.getById(未知来源)”
resultType="Building" 和 resultMap="Building" 我都试过了,结果是一样的。
我试图将那行代码替换为注释掉的代码。我将 getById 的结果类型更改为列表并获取列表的第 0 个元素。
在此变体中,代码工作正常。但我不喜欢这种转换,因为按 id 搜索总是 return 只有一个(或 none)对象。
如何使方法成为 return 单个对象,而不是列表?
我找到了问题的解决方案,所以我回答了我的问题。
异常的原因是我没有将 BuildingDbDto 声明为 public class。我想从业务层隐藏 DTO 并使其受包保护。我的目的是将 DTO 转换为同一包内的业务实体(包含业务逻辑的数据获取器和方法),并使业务实体 public.
不幸的是,MyBatis 内部的魔法必须能够访问返回值 classes,所以 DTO 必须是 public.
我想使用 MyBatis 3 从 PostgreSQL 数据库中检索数据。 我在界面上写了这个映射器:
package datamodel.gis.building;
public interface BuildingMapperBatis
{
// List of objects within rectangular box
public List<BuildingDbDto> getByBBox( @Param("lat1") BigDecimal lat1,
@Param("lon1") BigDecimal lon1,
@Param("lat2") BigDecimal lat2,
@Param("lon2") BigDecimal lon2 );
// Retrieve the object by id
public BuildingDbDto getById( @Param("id") Long id );
/// public List<BuildingDbDto> getById( @Param("id") Long id );
}
class BuildingDbDto 是一个普通的 DTO 对象,具有私有字段、public getter、没有 setter 和一个初始化所有字段的构造函数。
一块MyBatis XML配置是:
<configuration>
<typeAliases>
<typeAlias alias="Building" type="datamodel.gis.building.BuildingDbDto" />
</typeAliases>
<environments default="default">...here is the connection specified...</environments>
<mappers>
<mapper resource="datamodel/gis/building/BuildingMapperBatis.xml" />
</mappers>
</configuration>
文件“/src/main/resources/datamodel/gis/building/BuildingMapperBatis.xml”中mapper的XML配置为:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="datamodel.gis.building.BuildingMapperBatis">
<resultMap id="BuildingMap" type="Building" >
<id column="bld_id" property="id" />
<result column="bld_geo_latitude" property="latitude" />
<result column="bld_geo_longitude" property="longitude" />
<result column="bld_addr_settlement_name" property="addrSettlementName" />
</resultMap>
<select id="getByBBox" resultMap="BuildingMap">
SELECT bld_id, bld_geo_latitude, bld_geo_longitude, bld_addr_settlement_name
FROM get_buildings_in_bbox( #{lat1}, #{lon1}, #{lat2}, #{lon2} )
</select>
<!-- <select id="getById" resultMap="Building"> -->
<select id="getById" resultType="Building">
SELECT bld_id, bld_geo_latitude, bld_geo_longitude, bld_addr_settlement_name
FROM get_buildings_in_bbox( 0,0,90,90)
WHERE bld_id = #{id}
</select>
</mapper>
然后我执行查询:
BuildingMapperBatis mapper = sessionFactory.openSession().getMapper( BuildingMapperBatis.class );
List<BuildingDbDto> found = mapper.getByBBox( lat1, lon1, lat2, lon2 );
BuildingDbDto dto = mapper.getById( id );
/*///
BuildingDbDto dto = mapper.getById( id ).get(0);
*/
getByBBox 方法确实有效。
getById 方法在“.getById( id );”行抛出异常: “java.lang.IllegalAccessError:试图从 class com.sun.proxy 访问 class datamodel.gis.building.BuildingDbDto。$Proxy0 在 com.sun.proxy.$Proxy0.getById(未知来源)” resultType="Building" 和 resultMap="Building" 我都试过了,结果是一样的。
我试图将那行代码替换为注释掉的代码。我将 getById 的结果类型更改为列表并获取列表的第 0 个元素。 在此变体中,代码工作正常。但我不喜欢这种转换,因为按 id 搜索总是 return 只有一个(或 none)对象。
如何使方法成为 return 单个对象,而不是列表?
我找到了问题的解决方案,所以我回答了我的问题。
异常的原因是我没有将 BuildingDbDto 声明为 public class。我想从业务层隐藏 DTO 并使其受包保护。我的目的是将 DTO 转换为同一包内的业务实体(包含业务逻辑的数据获取器和方法),并使业务实体 public.
不幸的是,MyBatis 内部的魔法必须能够访问返回值 classes,所以 DTO 必须是 public.