NutzCN Logo
精华 自定义sql如何返回一个实体bean
发布于 2641天前 作者 qq_90c03f9d 3261 次浏览 复制 上一个帖子 下一个帖子
标签: dao
public List<NutMap> getUserFof(Integer userId){
        Sql sql = Sqls.create("select fof.id,fof.fullName,fof.shortName,fof.profitType,fof.createDate,fof.status," +
                "user.name as owner,pro.name as productType from `fof_info` fof " +
                "left join user_info user on fof.`userId` = user.id " +
                "left join product_type pro on fof.`productType` = pro.id " +
                "where fof.`userId` = @userId");
        sql.params().set("userId", userId);
        List<NutMap> nutMapList = this.list(sql);
        return nutMapList;
    }

如上的自定义sql如何返回一个实体bean,能不能根据set方法自动set呢?请大神解答!

15 回复

方法一: 按Record取出, 然后调用toEntity/toPojo方法,按不同的前置生成对象

方法二: 自定义SqlCallback

我理想的方法是自定义一个通用的sqlCallback 请给个 demo

        Sql sql = Sqls.create("select .....").setCallback(new SqlCallback() {
            public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
                List<Object> list = new ArrayList<>();
                while (rs.next()) {
                    // 根据不同属性组装对象
                    
                    // 放入list
                    list.add(xxx);
                }
                return list;
            }
        });
        List<MyPojo> list = dao.execute(sql).getList(MyPojo.class);

dao.getEntity(XXX.class)得到的Entity对象, 可以获取所有映射字段.

若不考虑oracle兼容性,可以参考 https://github.com/nutzam/nutz/issues/1050 里面的代码.

Map<String,Class> mysqlTypeMapping = new HashMap<String, Class>();
    {
        mysqlTypeMapping.put("INT",Integer.class);
        mysqlTypeMapping.put("VARCHAR",String.class);
        mysqlTypeMapping.put("TINYINT",Integer.class);
        mysqlTypeMapping.put("DATETIME",Date.class);
    }
    public List<T> listEntity(Sql sql){
        sql.setCallback(Sqls.callback.entities());
        sql.setEntity(dao().getEntity(getEntityClass()));
        sql.setCallback(new SqlCallback() {
            @Override
            public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
                List<T> list = new ArrayList<T>();
                Map<String,String> columns = new HashMap<String, String>();
                ResultSetMetaData rsmd = rs.getMetaData();
                for(int i=1;i<=rsmd.getColumnCount();i++){
                    columns.put(rsmd.getColumnLabel(i),rsmd.getColumnTypeName(i));
                }
                Entity<T> entity = dao().getEntity(getEntityClass());

                Class clazz = entity.getType();
                Method m = null;
                while (rs.next()) {
                    Object obj = null;
                    try{
                        obj = clazz.newInstance();
                        for(Map.Entry<String,String> entry : columns.entrySet()){
                            String columnName = entry.getKey();
                            String columnType = entry.getValue();
                            String methodName = "set" + StringUtil.upperInitial(columnName);
                            m = clazz.getMethod(methodName,mysqlTypeMapping.get(columnType));
                            if(null != m){
                                m.invoke(obj,rs.getObject(columnName));
                            }
                        }
                    }catch (Exception e){
                        continue;
                    }
                    list.add((T) obj);
                }
                return list;
            }
        });
        dao().execute(sql);
        List<T> list = sql.getList(getEntityClass());
        return list;
    }

大概写了一个还没完善 先放出来吧 也仅仅兼容mysql 可以先这么用着 后面等项目做完了完善了再放出来吧

没来得及写注释 有问题的话留言就行

又自己定义了一个callback,如下

public class TestCallback extends EntityCallback {

    protected String prefix;
    public TestCallback() {}
    public TestCallback(String prefix) {
        this.prefix = prefix;
    }

    @Override
    protected Object process(final ResultSet rs, final Entity<?> entity, final SqlContext context)
            throws SQLException {
        final Field[] fields = entity.getMirror().getFields(NutzTransient.class);
        ResultSetLooping ing = new ResultSetLooping() {
            protected boolean createObject(int index, ResultSet rs, SqlContext context, int rowCount) {
                Object obj = entity.getObject(rs, null, prefix);
                Method setMethod = null;
                for(Field field : fields){
                    try{
                        NutzTransient nutzTransient = field.getAnnotation(NutzTransient.class);
                        String fieldDbName = StringUtil.isBlank(nutzTransient.value()) ? field.getName() : "";
                        if(StringUtil.isNotBlank(prefix)){
                            fieldDbName = prefix + fieldDbName;
                        }
                        setMethod = entity.getMirror().getSetter(field);
                        if(null != setMethod){
                            setMethod.invoke(obj,rs.getObject(fieldDbName));
                        }
                    }catch (Exception e){
                        continue;
                    }
                }
                list.add(obj);
                return true;
            }
        };
        ing.doLoop(rs, context);
        return ing.getList();
    }
}

其中NutzTransient是自定义的一个注解,用于实体bean中没有映射数据库字段的实体字段。

我觉得要在nutzmore开个项目,专门放各种自定义的回调实现,供大家提交

@qq_90c03f9d @wendal 【dao()】是什么?

dao()是EntityService类的一个方法,返回值就是Dao

@qq_90c03f9d 可以把NutzTransient.class贴出来吗?万分感谢

添加回复
请先登陆
回到顶部