预言家:代码生活在一个使用JPA的Java-Webapp中,并且对它很满意,所以完全脱离JPA并不是解决方案。
但我的部分是关于动态数据查询。例如,假设管理员可以编写sql查询,用户可以触发这些查询来生成csv-导出。
使用JDBC,我获得了很多关于ResultSet的元数据,并且我可以在我知道它们的地方获取String和整数。
JPA允许直接进行SQL查询,但我只能以getResultList()
作为List<Object>
来获取这些查询,这实际上是一个List<Object[]>
或List<Object>
,这取决于select的列计数(据我所理解),并在将List<Object>
转换为List<Object[]>
时给出了一些难看的警告。
我理解JPA通常不能提供ResultSet
或JDBCConnection,因为它可以是对文本或大数据或memcache的访问,而不是SQL。但我还没有找到类似于SQL的东西。
在中使用直接和特定的EclipseLink方法是错误的,也是非常肮脏的。我可以肯定,应用程序将停留在SQL上,但不会停留在EclipseLink上。
因此,我似乎必须自己编写一个ResultSet,其中包含列计数和列名等元数据,而且无法从数据库结果中读取列的数据类型。但是,除了JPA之外,编写一个ResultSet类也是错误的,JPA存储了String中的一部分信息。
在JPA应用程序中打开一个额外的JDBC连接似乎解决了这个问题,但我甚至没有从JPA中获取连接数据,两个单独的配置迟早会导致厄运。
是我的用例太奇怪,还是JPA太有限,还是我对正确的解决方案视而不见?
SQL是一种非常强大和简单的语言,用于处理复杂的数据关系,所以我想知道为什么JPA会害怕它(当然,大量的典型对象--写和对象读取对于jdbc来说太痛苦了)。
有人知道JPA的现有ResultSet实现吗?还是我看不到的正确解决方案?
谢谢你的帮助。
发布于 2014-07-09 09:31:59
因为我只看到一些评论,所以我会尝试提供一个答案,但是由于这个问题没有一个非常具体的编程问题,我的答案将是相似的。
JPA是一个ORM,这意味着它将数据库内容映射到Java对象,并提供了更多的功能(事务、将EntityManager
操作转换为SQL查询、命名查询、.)。因为ORM在定义上是JDBC之上的一个层,所以它没有达到您需要的目的。
你说得对:
EntityManager
实例获取JDBC的标准方法,尽管它不是很好,但它也不像您想象的那么脏:创建一个从EntityManager返回JDBC的静态方法,这将是惟一的脏地方。如果要切换到Hibernate,则只需更改几行。Connection conn = em.unwrap(Session.class).connection();
您应该在JPA事务中以这种方式访问连接。否则,您将负责释放连接。(引用自这里)或者使用常规的JPQL查询来检索所有需要的数据,然后您将直接获得正确的类型。这里的限制是:它没有SQL那么灵活,而是很远(例如,您可以使用JPA2.1中的JOIN )。
发布于 2014-07-10 06:47:30
如果我正确地理解了您,您需要的是一个原生SQL查询(您可以与JPA一起使用该查询),然后将结果放入要操作的数据结构中,但不需要事先在实体中映射它,对吗?
然后,查询语言结果图(QLRM)项目可能对您有用,因为它允许您从本机查询创建结果对象,唯一的要求是为参数具有相同的数量和类型:
Query q = em.createNativeQuery("SELECT ID, NAME FROM EMPLOYEE");
List<EmployeeTO> list = jpaResultMapper.list(q, EmployeeTO.class);
如果您真的不了解即将出现的结果,因为它们是通用的,那么除了使用普通JDBC和检查元数据之外,您别无选择。
但是请记住,让用户建立自己的通用查询是潜在的危险,因为像SQL注入这样的事情可能会发生。最好尝试定义一些可能的构建块(使用准备好的语句和绑定变量,而不是字符串连接的SQL),您可以单独测试这些块,并让用户从中选择。
https://stackoverflow.com/questions/24524662
复制