需求背景
项目需求,将中间数据库的数据查询到本地视图,再将本地视图(千万级数据量)和会员表(百万级数据量)关联查询导出相关数据,
因为数据量比较大,一次全部查出或导致内存溢出,因此,后台需要对这些关联数据分页查询然后分批导出cvs文件,然后上传到媒体服务器。
需求实现过程中处理的问题
1.视图处理须知:将视图注解(配置)实体关系映射,并将添加的实体加入 persistence.xml 中;因为 查询实现的方式是 EJB JPA 实体管理器 创建的query,PersistenceContext(持久化上下文)上下文的配置文件中的 持久化单元 中配置的相关实体,否则会 出现 为 sql 语句中的变量赋值时,无法将传入的参数设置到sql语句中
1
java.lang.IndexOutOfBoundsException: Remember that ordinal parameters are 1-based!
这个问题产生的原因是 hibernate 通过 持久化上下文 中查找不到 相关实体,无法映射表结构,不能将参数设置到sql语句中,提示出这种很疑惑的问题,反复调试,能看到传入的变量值和创建出来的sql语句和sql变参,可就是无法将变量值设置给sql变参,后台日志输出上面的提示,很费解。
2.创建视图实体和联合主键:使用注解方式实现,参照 Hibernate怎样使用Annotation映射视图 和 Annotation对Hibernate中联合主键定义 将视图所有的字段放在联合主键实体中,该实体用
1
@Embeddable
注解,字段和普通实体一样使用
1
@Column
注解,在视图实体中使用该联合主键实体,用
1
@EmbeddedId @AttributeOverrides({...})
注解,这样视图映射关系已经搞定,因为开启了org.hibernate.tool.hbm2ddl.SchemaUpdate - Running hbm2ddl schema update,在启动过程中会报
1
2ERROR com.huanyu.common.jpa.index.OracleDbIndexBuilder - 创建“View_memcon”表主键(...)出错。
java.sql.SQLException: ORA-00942: 表或视图不存在
处理这个报错的方法是,关闭 hibernate hbm2ddl = none 即可,不需要更新索引,这个报错并不影响功能,只是在容器启动时报这么个错误看着不舒服,因为 本来 视图 就没有 主键 和 索引,这样去为视图 创建实体映射关系并添加联合主键,只是为了能使用 hibernate 去查询视图
3.关联查询语句: sql 语句 表、字段 is not mapped 问题
4.分批量导出多个文件: 因为写入单个文件的耗时线性增长,600万数据写入一个文件中,10多个小时没导完
视图处理
将视图映射成实体表,过程中 直接使用 em.createQuery(“数据库查询语句”) 报错:表 is not mapped 的问题,因此,引出了需要为视图创建实体和联合主键
创建视图实体和联合主键参照 Hibernate怎样使用Annotation映射视图 ,启动报关于视图 不存在的问题是因为开启了
更新表结构的配置,因此为视图更新表结构的时候创建联合主键时为视图更新索引报错,将 hibernate 的 hbm2ddl 配置关闭即可。
过程中,调试关于 java.lang.IndexOutOfBoundsException: Remember that ordinal parameters are 1-based! 的问题,反复调试总不知如何解决,后来得到指点
在 将添加的视图实体加入 persistence.xml 中 之后,这个问题得到解决
1 | 2016-01-13 10:32:26,742 [common-quartz-core.scheduler_Worker-2] ERROR com.huanyu.mbr.core.consumption.dao.ConsumptionDao - search(definition=WHERE |
这个问题 说明 对于 hibernate基础 掌握不扎实,对于 EJB JPA 概念理解不深
关联查询语句问题及处理(表、字段 not mapped )【hibernate 基础不扎实】
EJB JPA 实体管理器
1 | @PersistenceContext(unitName = "huanyu-mbr-core.persistent-unit") |
下述是问题,是因为 em.createQuery(“sql…”),其中 sql 中 直接使用了 数据库表名称(view_memcon),而不是 实体名称(Member)
对于 视图的字段属性 的 操作:select v.viewData.code from View_memcon v … 其中 View_memcon 是视图实体名称,v.viewData.code 是通过联合主键实体映射来映射视图字段
1 | java.lang.IllegalArgumentException: org.hibernate.hql.ast.QuerySyntaxException: view_memcon is not mapped [SELECT COUNT(m.id) FROM com.huanyu.mbr.core.consumption.dao.view_memcon v, t_mbr m WHERE m.id = v.memId AND v.unionCode = (select p.queryCode from t_consumption p where p.code = :code)] |
分批量导出多个文件
由于导出数据量比较大,导出单个文件写入耗时性能降低,需要分批量导出多个文件,压缩上传到媒体服务器;google 到 How to compress files in ZIP format
使用 java.util.zip.ZipEntry 进行导出操作
1 | AppCtxUtils 工具类 |
上述问题的处理解决过程中,个人 hibernate 基础 有待深入学习
参考资料
Hibernate怎样使用Annotation映射视图 和 Annotation对Hibernate中联合主键定义