MySQL版本:5.6.19
MySQL JDBC驱动版本:mysql-connector-java-5.1.30-bin
Hibernate版本:3.6.0
create table user ( id int not null, name varchar(10), areaid int, primary key (id) ); insert into user values(1, 'sean', 1); create table area ( areaid int not null, name varchar(10), primary key (areaid) ); insert into area values(1, 'Nanjing');
hibernate.cfg.xml:
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="show_sql">false</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://127.0.0.1:3306/test</property> <property name="connection.username">root</property> <property name="connection.password">123456</property> </session-factory> </hibernate-configuration>
HibernateTest.java:
package com.sean; import java.util.List; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateTest { public static void main(String[] args) { Configuration conf = new Configuration(); SessionFactory sessionFactory = conf.configure().buildSessionFactory(); Session session = sessionFactory.openSession(); StringBuilder strB = new StringBuilder(); strB.append("select u.name as userN, a.name as areaN "); strB.append("from user u left outer join area a "); strB.append("on u.areaid = a.areaid "); String sql = strB.toString(); System.out.println(sql); SQLQuery query = session.createSQLQuery(sql); List<Object[]> result = query.list(); for(Object[] objs : result) System.out.println(objs[0] + " " + objs[1]); } }
执行结果如下:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. select u.name as userN, a.name as areaN from user u left outer join area a on u.areaid = a.areaid Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute query at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.loader.Loader.doList(Loader.java:2536) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276) at org.hibernate.loader.Loader.list(Loader.java:2271) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316) at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842) at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165) at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157) at com.sean.HibernateTest.main(HibernateTest.java:22) Caused by: java.sql.SQLException: Column 'name' not found. at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1084) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:973) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:918) at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1162) at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5728) at org.hibernate.type.descriptor.sql.VarcharTypeDescriptor$2.doExtract(VarcharTypeDescriptor.java:61) at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:249) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:234) at org.hibernate.loader.custom.CustomLoader$ScalarResultColumnProcessor.extract(CustomLoader.java:505) at org.hibernate.loader.custom.CustomLoader$ResultRowProcessor.buildResultRow(CustomLoader.java:451) at org.hibernate.loader.custom.CustomLoader.getResultColumnOrRow(CustomLoader.java:348) at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:639) at org.hibernate.loader.Loader.doQuery(Loader.java:829) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274) at org.hibernate.loader.Loader.doList(Loader.java:2533) ... 7 more
实际上查询语句在MySQL中是可以正常执行的
可以将查询语句中的别名去掉,程序可以正常运行,但是查询结果不正确
select u.name, a.name from user u left outer join area a on u.areaid = a.areaid sean sean
解决方式:
最好的方式还是修改字段名称,如果不想修改字段名称,可以通过使用子查询的方式在表做关联之前,改变字段名称
select u.userN, a.areaN from (select name as userN, areaid from user) u left outer join (select areaid, name as areaN from area) a on u.areaid = a.areaid sean Nanjing
特意进行了验证以排除JDBC驱动的问题
package com.sean; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class JDBCTest { public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection( "jdbc:mysql://127.0.0.1:3306/test", "root", "123456"); Statement stat =conn.createStatement(); StringBuilder strB = new StringBuilder(); strB.append("select u.name as userN, a.name as areaN "); strB.append("from user u left join area a "); strB.append("on u.areaid = a.areaid"); String sql = strB.toString(); System.out.println(sql); ResultSet rs = stat.executeQuery(sql); while(rs.next()){ System.out.println(rs.getString(1) + " " + rs.getString(2)); } } }
执行结果如下:
select u.name as userN, a.name as areaN from user u left join area a on u.areaid = a.areaid sean Nanjing