13

我有一个使用 mybatis 进行对象持久化的应用程序。但是我有可能需要运行任意 sql(来自用户)。我可以用mybatis做吗?

更新:

我选择使用 dbutils (JDBC) 来运行用户定义的 sql,但是我需要一个 DataSource 的实例来创建 QueryRunner。有什么办法可以从 mybatis 获取数据源?

4

5 回答 5

15

我使用这个实用类:

import java.util.List;
import org.apache.ibatis.annotations.SelectProvider;

public interface SqlMapper {
    static class PureSqlProvider {
        public String sql(String sql) {
            return sql;
        }

        public String count(String from) {
            return "SELECT count(*) FROM " + from;
        }
    }

    @SelectProvider(type = PureSqlProvider.class, method = "sql")
    public List<?> select(String sql);

    @SelectProvider(type = PureSqlProvider.class, method = "count")
    public Integer count(String from);

    @SelectProvider(type = PureSqlProvider.class, method = "sql")
    public Integer execute(String query);
}
于 2012-11-16T18:28:42.303 回答
4

您的问题类似于How to exequte query directly from java code using mybatis?

我已经给出了这个问题的答案。但我希望这个解决方案能帮助你。

Mybatis 已经有这个功能了,但是你必须使用适配器,如下所示。

  1. 创建一个适配器类;

     public class SQLAdapter {  
     String sql;  
    
     public SQLAdapter(String sql) {  
         this.sql = sql;  
     }  
    
     public String getSql() {  
         return sql;  
     }  
    
     public void setSql(String sql) {  
         this.sql = sql;  
     }   }
    
  2. 创建类 SQLAdapter 的 typeAlias

<typeAlias alias="sqladapter" type="com.zj.xxx.xxx.SQLAdapter" />

  1. 在需要直接执行 sql 的每个对象 xml 中放置选择标记。

     <select id="findRecords" parameterType="SQLAdapter" resultMap="xxxxxResultMap">  
         ${sql}  
     </select> 
    
  2. 像这样调用这个选择方法

String _sql = "select * from table where... order by... limit...";
xxxxx.findRecords(new SQLAdapter(_sql));
  1. 事情都已经做好了。你不能再在 xml 文件中编写复杂的 sql 语言。祝你好运。
于 2014-10-11T02:30:33.430 回答
2

根据提供的答案,它们都很好。但是它们都需要使用一个Adapter类。

使用Mybatis 版本 3,我成功地使用了 aHashMap<String, String>来保存和传递SQL

请参阅下面的代码。

Mapper课堂上

final String sql = "${sql}";

@Select(sql)
void execute(HashMap<String, String> m);

调用方法时:

String sql = "SELECT * FROM record limit 1";
HashMap<String, String> map = new HashMap<String, String>();
map.put("sql", sql);
mapper.execute(map);

HashMap提供了一种无需在代码中定义 Class 属性或字段的方法,您可以使用 Map 重新定义它。

谢谢。

于 2017-04-19T09:43:26.073 回答
1

可重用的 SQL 片段可用于动态创建查询的选择部分。在您的映射器中,将查询作为普通参数传递:

@Param("sql")String sql

在您的查询中,只需使用${sql}而不是#{sql}访问参数。参数 sql 中的值可以是完全有效的 sql 查询或 sql 查询的片段。

于 2017-12-18T10:24:00.853 回答
1

为了测试我使用

import org.apache.ibatis.jdbc.ScriptRunner;
import java.io.Reader;
import java.io.StringReader;
    
public class test {
        private static final String conf = "mybatis.conf.xml";

        private SqlSessionFactoryBuilder builder;
        private SqlSessionFactory sessionFactory;
        Reader reader;
        private SqlSession session;
        private ScriptRunner runner;
       
    @Before
    public void before() {
        builder = new SqlSessionFactoryBuilder();

        try {
            reader = Resources.getResourceAsReader(conf);
        } catch (IOException e) {
            e.printStackTrace();
        }

        sessionFactory = builder.build(reader);

        session = sessionFactory.openSession();
        runner = new ScriptRunner(session.getConnection());
        runner.setAutoCommit(true);
        runner.setStopOnError(true);
    }

    @Test   
    public void testSelectChapelStatus() {  
        Reader populate = new StringReader("insert into person values (7553,0,'201002496','Wish','Jill','Rain',1,0,NULL,'xxx@LCU.EDU');\r\n"
                + "");
         runner.runScript(populate);
    }
于 2021-06-23T18:23:26.143 回答