Ibatis / MyBatis动态选择,无需创建任何Pojo / Mapper

时间:2011-07-05 11:38:03

标签: ibatis mybatis

有没有办法使用Ibatis / MyBatis动态选择/更新/删除?

当我说“动态”时,这意味着我根本不想创建任何POJO / DataMapper。

欢迎任何网址示例。

4 个答案:

答案 0 :(得分:8)

是的,只需将resultType属性设置为map,表格数据将放入列名称的HashMap中。如果查询返回多于1行,则映射的行将放入List中。如果要选择单个列,则只能获取该值(如String,int等)或列表。

<select id="test1" resultType="map">select * from user</select>
<select id="test2" resultType="map" parameterType="int">
  select * from user where id=#{value}</select>
<select id="test3" resultType="string">select name from user</select>
...
// returns a list of maps
List test = sqlSession.selectList("test1");

// returns a single map
Object map = sqlSession.selectOne("test2", 0);

// returns a list of strings
List names = sqlSession.selectList("test3");

这适用于MyBatis 3;我想你可以在iBatis 2中做类似的事情。

答案 1 :(得分:2)

以下方法可能很有用。 比如说,你有一些通用的选择界面,比如:

add_filter( 'authenticate', 'chk_active_user',100,2);
function chk_active_user ($user,$username) 
   {
     $user_data = $user->data;
     $user_id = $user_data->ID;
     $user_sts = get_user_meta($user_id,"user_active_status",true);
     if ($user_sts==="no")
     {
        return new WP_Error( 'disabled_account','this account is disabled');

      }
      else
      {
       return $user;
      }
        return $user;
     }

根据某些外部类型(例如,单列或日期范围或范围),您可以在模板public interface IAutoRepository { /** * The automatically generated insertPKs sql statements. * Parts of the query can be set manually in the sql (insert-select query). * * @param items the {@link WhereStmt} statements * @return the inserted rows count */ @Transactional <T extends WhereStmt> Integer insertPKs(@Param("items") List<T> items); /** * Returns the value based on the {@link Parameter} class * * @param param the {@link Parameter} instance * @return the searched value in a {@link java.util.Map} form */ @MapKey("VAL") <T extends Parameter> Map<String, Map<String, ?>> getDistinctValues(@Param("param") T param); } 中定义以下查询:

Common.xml

你从mybatis收到的是java.util.Map。然后你就可以使用它了:

<sql id="includeDistinctValues">
SELECT
    <choose>
        <when test='param.type.name() == "set"'>
            DISTINCT ${param.column} AS val
        </when>
        <when test='param.type.name() == "date" or param.type.name() == "range"'>
            <some uid>              AS val,
            MIN(${param.minColumn}) AS min,
            MAX(${param.maxColumn}) AS max
        </when>
    </choose>
FROM ${entityTable}
</sql>

其中SetParameter可以表示如下:

public enum StmtType {
    set((valMap) -> {
        final Set<String> distinctValues = valMap
                .values()
                .stream()
                .map(val -> (String) val.get("VAL"))
                //use in date/range case
                //final Date minDate = (Date) val.get("MIN");
                //final Date maxDate = (Date) val.get("MAX");
                .collect(Collectors.toSet());
        return distinctValues;
    },
            (values, params) -> {
                final SetParameter parameter = (SetParameter) params.getParams();
                return new WhereSetStmt<>(parameter.getColumn(), values, params.getIncludeEmptyValues());
            });
    @Getter
    private Function<Map<String, Map<String, ?>>, ? extends Iterable> toValue;
    @Getter
    private BiFunction<Collection, DataParam, ? extends WhereStmt> toWhereStmt;

    StmtType(
            Function<Map<String, Map<String, ?>>, ? extends Iterable> toValue,
            BiFunction<Collection, DataParam, ? extends WhereStmt> toWhereStmt
    ) {
        this.toValue = toValue;
        this.toWhereStmt = toWhereStmt;
    }
}

此外,您可以定义一些WhereStmt,如:

@Getter
public class SetParameter extends Parameter {
    /**
     * Column in sql query,
     */
    private final String column;
    public SetParameter(String column) {
        super(StmtType.set);
        this.column = column;
    }
}

最后,在mybatis generic public abstract class WhereStmt { /** * Type of the statement */ private final StmtType type; /** * Shall empty values be included. */ private final boolean includeEmptyValues; } @Getter public class WhereSetStmt<T> extends WhereStmt { /** * The column for `column` IN (...) statement */ private String column; /** * Values for `column` IN (...) statement */ private Collection<T> values; public WhereSetStmt(String column, Collection<T> values, boolean includeEmptyValues) { super(StmtType.set, includeEmptyValues); this.column = column; this.values = values; } } @Getter @AllArgsConstructor public final class DataParam<P extends Parameter> { /** * Whether to include nullable values. */ private final Boolean includeEmptyValues; /** * Represents database required information for later processing and sql statements generation. */ private final P params; } 中,你可以使用它:

Common.xml

并将sql语句组合为模板,例如:

<sql id="includeInsertPkSelect">
    SELECT DISTINCT(${id})
    FROM ${entityTable}
</sql>

<sql id="includeInsertPkWhere">
    <if test="items != null and items.size() > 0">
        AND
        <foreach collection="items" item="item" index="i" separator="AND">
            <choose>
                <when test='item.type.name() == "set" and ( item.values != null and item.values.size() > 0 or item.includeEmptyValues )'>
                    (
                    <if test="item.values != null and item.values.size() > 0">
                        ${item.column} IN
                        <foreach item="value" collection="item.values" separator="," open="("
                                 close=")">
                            #{value}
                        </foreach>
                        <if test="item.includeEmptyValues">
                            OR
                        </if>
                    </if>
                    <if test="item.includeEmptyValues">
                        ${item.column} IS null
                    </if>
                    )
                </when>

                <when test='item.type.name() == "date"'>
                    (
                    COALESCE(${item.column}, SYSDATE + 1000000)
                    BETWEEN #{item.from} AND #{item.to}
                    <if test="item.includeEmptyValues">
                        OR ${item.column} IS NULL
                    </if>
                    )
                </when>
                <when test='item.type.name() == "range"'>
                    (
                    COALESCE(${item.column}, 1000000000)
                    BETWEEN #{item.from} AND #{item.to}
                    <if test="item.includeEmptyValues">
                        OR ${item.column} IS NULL
                    </if>
                    )
                </when>
            </choose>
        </foreach>
    </if>
</sql>

答案 2 :(得分:0)

是的,应该可以通过API在运行时构建映射,并使用Maps而不是实体类。

答案 3 :(得分:0)

是的,您可以不使用POJO进行选择/更新/删除。 在myBatis中,您可以使用Mapper XML编写查询,并设置将从SQL语句返回的resultType并将其存储在对象中。

例如,

    <mapper namespace = "data">
      <select id = "fetch" resultType = "java.util.HashMap">
        select * from table_name
      </select>
    </mapper>

您可以使用“地图列表”存储这些结果。

  List<Map<String,Object>> results = session.selectList("data.fetch");