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