【问题标题】:Is there any library to represent SQL queries as objects in Java code? [closed]是否有任何库可以将 SQL 查询表示为 Java 代码中的对象? [关闭]
【发布时间】:2010-10-23 22:23:47
【问题描述】:

我想知道是否有任何库可用于将 SQL 查询表示为 Java 中的对象。

在代码中,我有大量 java.lang.String 类型的静态变量,它们是手写 SQL 查询。我会寻找具有良好 fluent API 的库,它允许我将查询表示为对象而不是字符串。

例子:

Query q = select("DATE", "QUOTE")
  .from("STOCKMARKET")
  .where(eq("CORP", "?"))
  .orderBy("DATE", DESC);

【问题讨论】:

    标签: java sql api fluent


    【解决方案1】:

    您可以使用 naskarlab/fluent-query:

    https://github.com/naskarlab/fluent-query

    例子:

    @Test
    public void testSelect() {
        String expected = "select e0.* from Customer e0";
    
        String actual = new QueryBuilder()
            .from(Customer.class)
            .to(new NativeSQL())
            .sql()
            ;
    
        Assert.assertEquals(expected, actual);
    }
    

    您可以在项目的单元测试中看到更多示例:

    https://github.com/naskarlab/fluent-query/blob/master/src/test/java/com/naskar/fluentquery/TestNativeSimpleConventionQueryTest.java

    【讨论】:

      【解决方案2】:

      Apache Empire-db 是一个关系数据库抽象层和数据持久性组件,与传统的对象关系映射框架 (ORM) 相比,它允许开发人员在应用程序开发中采用更加以 SQL 为中心的方法。

      更多: https://empire-db.apache.org/

      Quaere

      http://xircles.codehaus.org/projects/quaere

      【讨论】:

      • quaere 是活跃的项目吗?他们网站上的内容很少。
      • 我一般不是 quaere 用户。请记住它是几年前的 java-can-have-linq 炒作之一。从邮件列表存档表明该项目确实不是很活跃。 FWIW,浏览邮件列表,向我展示一些您可能想看看的类似项目。 JaQu(h2database.com/html/jaqu.html) 页面底部也参考so一些其他相关项目
      【解决方案3】:

      这些是一些很好的专有库,可以动态创建类型安全的 SQL 查询

      除了以上,总有

      • 休眠/JPA 标准查询
      • MyBatis

      你在 jOOQ 中的例子:

      create.select(DATE, QUOTE)
            .from(STOCKMARKET)
            .where(CORP.equal(123))
            .orderBy(DATE.desc());
      

      【讨论】:

        【解决方案4】:

        Querydsl 支持查询 SQL、JPA 和 JDO 后端。

        上面的例子变成:

        query.from(stockmarket).where(stockmarket.corp.eq(someVar))
            .orderBy(stockmarket.date.desc())
            .list(stockmarket.date, stockmarket.quote);
        

        Querydsl 通过 APT 使用代码生成将 SQL 模式镜像到 Java 查询类型。这样,查询就完全是类型安全的(或与 SQL 的“模式兼容”)。

        我是Querydsl的维护者,所以这个答案是有偏见的。

        我发布了 Querydsl 与其他框架的比较here

        【讨论】:

          【解决方案5】:

          Jequel 看起来很漂亮:http://www.jequel.de/

          它使用流畅的界面,因此易于阅读,几乎就像自然 SQL(来自文档):

          SqlString sql = select(ARTICLE.OID)
                         .from(ARTICLE, ARTICLE_COLOR)
                         .where(ARTICLE.OID.eq(ARTICLE_COLOR.ARTICLE_OID)
                         .and(ARTICLE.ARTICLE_NO.is_not(NULL)));
          

          它还支持对带有参数的 DataSource 执行查询,因此它也可以处理参数化查询的创建。

          【讨论】:

          • 看起来不错。这就是我一直在寻找的东西。干杯!
          • 不错!不要忘记回来发布您的发现。前几天才知道的,还没有机会用很多,但我打算以后用。
          • 大约一年前我联系了 Jequel 的开发者。这个项目似乎在 2008 年进入了维护模式......
          【解决方案6】:

          如果您不想映射字符串查询,那么您必须将您的类注释为实体并将其与表绑定,然后您可以使用 hibernate 或 java 持久性。示例将太复杂。但是,最后你的查询会变成这样:

          查找实体列表:

           Criteria c = createCreteria(entityManager, StockMarket.class);
              // you can add "where" clause by using c.add(Restrictions); 
             // like this: c.add(Restrictions.ilike("name", "%somename%"); where "name" is your entity's field
               List<StockMarket> smList = c.list();
          

          通过 id 查找对象:

           StockMarket sm  = entityManager.find(StockMarket.class, id);
          

          【讨论】:

            【解决方案7】:

            http://www.hibernate.org/ 可能是 Java 最强大的 ORM 库。它可以做的不仅仅是简单的查询映射。因此,您可以轻松地在应用程序的其他地方实现它。 对于您的情况,可以这样做:

            public class LookupCodeName
            {
                private String code;
                private String name;
            
             /*... getter-setters ... */
            }
            
            public class someBL {
            
            public List<LookupCodeName> returnSomeEntity() {
                  SQLQuery sqlQuery =  (SQLQuery)((HibernateSession)em).getHibernateSession()
                                    .createSQLQuery( "SELECT st.name as name, st.code as code FROM someTable st")
                                    .addScalar("code")
                                    .addScalar("name")
            .setResultTransformer(Transformers.aliasToBean(LookupCodeName.class));
                }
            return (List<LookupCodeName>)sqlQuery.list();
            }
            

            【讨论】:

            • 是的,我知道 Hibernate,但在您的示例中,仍然有硬编码的 SQL 表示为字符串(“SELECT st.name as name,st.code as code FROM someTable st”)。也许我的问题不够清楚,但我想用对象表示替换字符串查询,而不是使用强大的框架来执行查询。
            • Pregzt,你可能想看看 Hibernate Criterias
            • 我认为标准 API 会从拥有 SQL 构建器 API 中引出错误的方向。在我当前的项目中,最初的(并且早已不复存在的)开发人员使用了标准 API,而当前的团队讨厌它。我们可以使用本机 SQL 完成 DAO 方法,只需编写标准 API 所需的一半时间,因为我们通常最终会查看标准 API 生成的 SQL 来验证其正确性。如果您已经知道正确的 SQL,为什么还要依赖 SQL 生成器?
            • 如果您已经知道正确的 SQL,为什么还要依赖 SQL 生成器?您的所有评论都基于此语句。但是为什么你认为你“知道正确的 SQL”?只是一些事情,hibernate 代表: 1. sql 可能太复杂而无法多次编写。(例如复杂的实体关系) 2. 如果您更改实体 - 您不需要更改新的正确数据映射的标准。 3.您知道您的应用程序将在哪个数据库上运行吗?硬编码的 SQL 扼杀了一些独立性。
            • 上面的示例使用的是普通 SQL,这很糟糕,因为这通常意味着您的应用程序只是依赖于一个特定的 SQL 引擎,而不是能够在任何数据库后端上运行。相反,建议使用 HQL(Hibernate Query Language),它在后台被翻译成 SQL。但是这种方法仍然使用字符串,因此重构可能会破坏内容。我通过使用一个很好的 IDE (IntelliJ) 来解决这个问题,它支持 HQL 的重构。
            猜你喜欢
            • 2023-03-17
            • 2011-05-24
            • 1970-01-01
            • 2012-12-11
            • 2016-11-20
            • 1970-01-01
            • 2011-03-25
            • 1970-01-01
            • 2014-02-12
            相关资源
            最近更新 更多