使用Hibernate+MySql+native SQL的BUG,以及解决办法
本来是mssql+hibernate+native SQL 应用的很和谐
但是到了把mssql换成mysql,就出了错(同样的数据结构和数据)。
查询方法是:
- String sql =
- "select id XXX_ID from t_tab";
- List<Map> list = session.createSQLQuery(sql)
- .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
- .list();
错误信息:
- org.hibernate.exception.SQLGrammarException: could not execute query
- at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
- at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
- at org.hibernate.loader.Loader.doList(Loader.java:2231)
- at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
- at org.hibernate.loader.Loader.list(Loader.java:2120)
- at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:312)
- at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1722)
- at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
- at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:175)
- at com.exsun.common.dao.BasDaoImpl.findBySql(BasDaoImpl.java:173)
- at com.exsun.arms.service.EmployeesalaryService.getList(EmployeesalaryService.java:32)
- at com.exsun.arms.service.EmployeesalaryService$$FastClassByCGLIB$$2d81000f.invoke(<generated>)
- at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
- at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:700)
- at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
- at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
- at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
- at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
- at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
- at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
- at com.exsun.arms.service.EmployeesalaryService$$EnhancerByCGLIB$$1e3e6d9f.getList(<generated>)
- at com.exsun.arms.action.EmployeesalaryAction.getList(EmployeesalaryAction.java:110)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:269)
- at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:170)
- at org.springframework.web.struts.DelegatingActionProxy.execute(DelegatingActionProxy.java:110)
- at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:58)
- at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:67)
- at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
- at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
- at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:305)
- at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
- at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
- at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
- at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:449)
- at javax.servlet.http.HttpServlet.service(HttpServlet.java:627)
- at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
- at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
- at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
- at com.exsun.common.util.MenuFilter.doFilter(MenuFilter.java:103)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
- at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
- at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
- at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
- at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
- at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
- at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
- at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
- at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:873)
- at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
- at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
- at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
- at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
- at java.lang.Thread.run(Thread.java:619)
- Caused by: java.sql.SQLException: Column 'id' not found.
- at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1072)
- at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:986)
- at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:981)
- at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
- at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1144)
- at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5616)
- at org.hibernate.type.StringType.get(StringType.java:41)
- at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:184)
- at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:210)
- at org.hibernate.loader.custom.CustomLoader$ScalarResultColumnProcessor.extract(CustomLoader.java:497)
- at org.hibernate.loader.custom.CustomLoader$ResultRowProcessor.buildResultRow(CustomLoader.java:443)
- at org.hibernate.loader.custom.CustomLoader.getResultColumnOrRow(CustomLoader.java:340)
- at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:629)
- at org.hibernate.loader.Loader.doQuery(Loader.java:724)
- at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
- at org.hibernate.loader.Loader.doList(Loader.java:2228)
- ... 62 more
看到最后Caused by: java.sql.SQLException:
所以我试试用JDBC连接
- public class TestMySqlJDBC {
- public static void main(String[] args) throws Exception, IllegalAccessException, ClassNotFoundException {
- Class.forName("com.mysql.jdbc.Driver").newInstance();
- Connection con=java.sql.DriverManager.getConnection("jdbc:mysql://localhost:3306/arms?useUnicode=true&characterEncoding=utf8&","root","");
- Statement stmt=con.createStatement();
- ResultSet rs=stmt.executeQuery("select id XXX_ID,name from t_tab");
- while(rs.next())
- {
- System.out.printf("id:%s___name:%s/n",rs.getString("XXX_ID"),rs.getString("name"));
- }
- rs.close();
- stmt.close();
- con.close();
- }
- }
可以很正常的运行。
后来仔细又看了一下hibernate的执行错误
Caused by: java.sql.SQLException: Column 'id' not found.
是ID 找不到 不是XXX_ID 找不到。这意思貌似hibernate就没按别名alias 来取值
跟踪了一下hibernate
其中在Customer里发现的这一段
- public class ScalarResultColumnProcessor implements ResultColumnProcessor {
- private int position = -1;
- private String alias;
- private Type type;
- public ScalarResultColumnProcessor(int position) {
- this.position = position;
- }
- public ScalarResultColumnProcessor(String alias, Type type) {
- this.alias = alias;
- this.type = type;
- }
- //这个方法中的alias 为"id"而不是XXX_ID
- public Object extract(
- Object[] data,
- ResultSet resultSet,
- SessionImplementor session) throws SQLException, HibernateException {
- return type.nullSafeGet( resultSet, alias, session, null );
- }
- ...........
- ...........
- ...........
hibernate是按照select id,name from tab来解释
而不是 select id XXX_ID , name from tab
这里跟到的数据果然是Hibernate把alias给忽略了。。。
-------------------------------------
继续跟踪hibernate代码.根据调用栈,单步跟踪很快找到
org.hibernate.loader.custom.CustomLoader$ScalarResultColumnProcessor 里面的
- public void performDiscovery(Metadata metadata, List types, List aliases) throws SQLException {
- if ( alias == null ) {
- alias = metadata.getColumnName( position );
- }
- else if ( position < 0 ) {
- position = metadata.resolveColumnPosition( alias );
- }
- if ( type == null ) {
- type = metadata.getHibernateType( position );
- }
- types.add( type );
- aliases.add( alias );
- }
这里就是拼装将来要根据列名get出来的结果的地方
alias = metadata.getColumnName( position )
getColumnName 跟进去就是JDBC的实现.
跟踪可以看到.从这里get出来的alias不是真正的aliasName,而是originalColumnName原始列名.
后来试着修改了hibernate各种方言的设置:MySQLDialect,MySQL5Dialect,MySQL5InnoDBDialect等等还是不行。
我用JDBC试了下
mysql-connector-java-5.1.9-bin.jar
mysql-connector-java-5.1.10-bin.jar
mysql-connector-java-5.1.11-bin.jar
- ResultSet rs=stmt.executeQuery(sql);
- ResultSetMetaData rsmd = rs.getMetaData();
- int columnCount = rsmd.getColumnCount();
- List<String> columnName = new ArrayList();
- for (int i = 1; i <= columnCount; i++) {
- String tmp = rsmd.getColumnName(i) + "___" + rsmd.getColumnLabel(i);
- System.out.println(tmp);
- }
三个实现,结果都是一样的.
mysql的JDBC要获取alias只能用getColumnLable,不能用getColumnName
而Hibernate取字段名称的时候就只用 getColumnName.
解决办法有两个,一个是改hibernate,再不就得改mysql.
怕Hibernate对别的数据库实现有影响
所以就拿mysql的JDBC驱动开刀了.
把com.mysql.jdbc.ResultSetMetaData
中的
- public String getColumnName(int column) throws SQLException {
- if (this.useOldAliasBehavior) {
- return getField(column).getName();
- }
- String name = getField(column).getNameNoAliases();
- if (name != null && name.length() == 0) {
- return getField(column).getName();
- }
- return name;
- }
修改为:
- public String getColumnName(int column) throws SQLException {
- return getColumnLable(column);
- }
然后把JDBC重新打包一下
再运行就OK了.
使用Hibernate+MySql+native SQL的BUG,以及解决办法的更多相关文章
- 13.hibernate的native sql查询(转自xiaoluo501395377)
hibernate的native sql查询 在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hi ...
- Mysql文件太大导入失败解决办法总结
Mysql文件太大导入失败解决办法总结 在使用phpmyadmin导入数据库的时候可能会碰到由于数据库文件太大而无法导入的问题! 英文提示如下:File exceeds the maximum all ...
- Dumpzilla工具第615行bug的解决办法
Dumpzilla工具第615行bug的解决办法 在Dumpzilla使用选项frequency时,会提示SQL语法错误.这是由于其中SQL语句编写错误.需要将615行中: where url l ...
- MySQL8.0报错Can't connect to MySQL server on 'localhost' (10061)的解决办法
MySQL8.0报错Can't connect to MySQL server on 'localhost' (10061)的解决办法 事情的起因 今天课堂上要展示小组项目,需要用一个软件叫W ...
- 【转载】IE浏览器常见的9个css Bug以及解决办法
IE浏览器常见的9个css Bug以及解决办法 我们在浏览网页的时候经常看见这样的现象:某个网页在IE6浏览器中打开很正常,但是在IE8里面打开可能完全变形了.或者也有可能出现完全相反的现象.这让We ...
- 无法启动MYSQL服务”1067 进程意外终止”解决办法
原文:http://www.111cn.net/database/mysql/48888.htm 本文章主要是总结了各种导致mysql提示无法启动MYSQL服务"1067 进程意外终止& ...
- 无法启动mysql服务”1067 进程意外终止”解决办法【简记】
本文章主要是总结了各种导致mysql提示无法启动MYSQL服务”1067 进程意外终止”的一些解决办法,有碰到mysql无法启动的同学可尝试参考. 在win7的服务器里开启MySql服务提示“wind ...
- mysql的大量的sleep进程解决办法
mysql的大量的sleep进程解决办法 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/liuyong0507/article/detai ...
- windows下运行命令行mysql,提示mysql不是内部命令,解决办法
1. 打开CMD命令行,连接本地mysql数据库:mysql -u root -p 提示‘mysql’不是本地命令,解决办法如下: 找到你安装的mysql的目录,打开当前目录下的bin文件夹,你可以看 ...
随机推荐
- ES5-bind用法及与以前的apply和call
当我们调用一个函数的时候,函数中的this一般是指向调用者的.但是我们其实可以在调用函数的时候,传入一个对象,让函数中的this指向我们传入的对象,而不是调用者本身. apply,call,bind都 ...
- MAC系统 - 基础知识
一.基础操作 设置:触控板设置 - >学习具体手势 手势:MacBook Pro手势大全必学手势触控板手势有哪些 左键,右键,滑屏,切换到应用... 一指操作: 一指敲击:鼠标左键: 一指按下: ...
- 【PAT甲级】1052 Linked List Sorting (25 分)
题意: 输入一个正整数N(<=100000),和一个链表的头结点地址.接着输入N行,每行包括一个结点的地址,结点存放的值(-1e5~1e5),指向下一个结点的地址.地址由五位包含前导零的正整数组 ...
- linux文件或目录属性
wc(word count)命令的功能:统计指定文件的字节数.字数.行数.,并将统计结果显示输出 命令参数: -c 只显示字节数 -l 只显示行数 -w 只显示字数 od命令:查看二进制文件信息 ...
- 大数据篇:MapReduce
MapReduce MapReduce是什么? MapReduce源自于Google发表于2004年12月的MapReduce论文,是面向大数据并行处理的计算模型.框架和平台,而Hadoop MapR ...
- Day11 - D - Race to 1 Again LightOJ - 1038
设dp_i为所求答案,每次选择因数的概率相同,设i有x个因数,dp_i=sum(1/x*x_j)+1,(x_j表示第j个因数),那我们就预处理每个数的因数即可,T=10000,需要预处理出答案 #in ...
- springboot后端时间到前端,相差8小时,时间格式不对
spring boot后台时间正确,返回给前台的时间不正确,和后台差8个小时 { "code": 1, "msg": "SUCCESS", ...
- 项目中常用的全局宏定义#define
一 关于屏幕大小 #pragma mark - 屏幕宽高 #define SCREEN_BOUNDS ([UIScreen mainScreen].bounds) #define SCREEN_WID ...
- 重新理解CEO的学习能力----HHR计划----以太入门课--第一课
一共5个小节. 第一节:开始学习 1,投资人最看重的一点:CEO的学习能力. (因为CEO需要:找优秀的合伙人,需要市场调研,机会判断,组建团队,验证方向,去融资,冷启动,做增长,解决法务,财务,税务 ...
- Struts笔记二:栈值的内存区域及标签和拦截器
值栈和ognl表达式 1.只要是一个MVC框架,必须解决数据的存和取的问题 2.struts2利用值栈来存数据,所以值栈是一个存储数据的内存结构 1. ValueStack是一个接口,在struts ...