项目场景:
SpringMVC项目,关于mybatis一对多关联查询的问题。问题描述:
错误提示: Statement returned more than one row, where no more than one was expectedmn.java:
public class Mn {
private int m;
private int n;
@Override
public String toString() {
return "Mn{" +
"m=" + m +
", n=" + n +
'}';
}
}
xyz.java:
@Repository
public class Xyz {
private String x;
private String y;
private String z;
private List<Mn> mns;
@Override
public String toString() {
return "Xyz{" +
"x='" + x + '\'' +
", y='" + y + '\'' +
", z='" + z + '\'' +
", mn=" + mns +
'}';
}
}
daomapper.java:
@Results({
@Result(property = "x" ,column = "x"),
@Result(property = "y" ,column = "y"),
@Result(property = "z" ,column = "z"),
@Result(
property = "mns",
column = "x",
javaType = Mn.class,
many = @Many(select ="package1.mapper.DaoMapper.getMn" )
)
})
@Select("select * from xyz where x=${k}")
List<Xyz> daoSelect1(int k);
@Results(id = "mnMap",
value = {
@Result(property = "m" , column = "m"),
@Result(property = "n" , column = "n")
})
@Select("select * from mn where m=${m}")
List<Mn> getMn(int m);
测试类:
public class MybatisTest {
private DaoMapper daoMapper;
@Before
public void initMapper() throws IOException {
InputStream inputStream=Resources.getResourceAsStream("mybatisConfig.xml");
SqlSession sqlSession=new SqlSessionFactoryBuilder().build(inputStream).openSession();
daoMapper =sqlSession.getMapper(DaoMapper.class);
}
@Test
public void mybatistest1() throws IOException {
List<Xyz> xyzs = daoMapper.daoSelect1(2);
for(Xyz x:xyzs ){
System.out.println(x.toString());
}
}
}
控制台:
Created connection 1541708640.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5be49b60]
==> Preparing: select * from xyz where x=2
==> Parameters:
<== Columns: x, y, z
<== Row: 2, 1, 44
====> Preparing: select * from mn where m=2
====> Parameters:
<==== Columns: m, n
<==== Row: 2, 2222
<==== Row: 2, 3333
<==== Total: 2
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.executor.ExecutorException: Statement returned more than one row, where no more than one was expected.
### The error may exist in package1/mapper/DaoMapper.java (best guess)
### The error may involve package1.mapper.DaoMapper.getMn
### The error occurred while handling results
### SQL: select * from mn where m=2
### Cause: org.apache.ibatis.executor.ExecutorException: Statement returned more than one row, where no more than one was expected.
......
原因分析以及解决方案:
错误报告显示应该返回一条数据,但是却返回了多条数据。这就比较迷惑了,对于xyz类中的mns,我的期望就是返回多条数据。
网上找了很久都没找到解决办法,后来我自己又仔细检查了代码,发现是一个很小的问题
javaType = Mn.class
我的xyz类中的mns是ListMn类型,但是这里写的是Mn类型。
把这句代码删掉,运行测试类,成功!
Created connection 1541708640.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5be49b60]
==> Preparing: select * from xyz where x=2
==> Parameters:
<== Columns: x, y, z
<== Row: 2, 1, 44
====> Preparing: select * from mn where m=2
====> Parameters:
<==== Columns: m, n
<==== Row: 2, 2222
<==== Row: 2, 3333
<==== Total: 2
<== Total: 1
Xyz{x='2', y='1', z='44', mn=[Mn{m=2, n=2222}, Mn{m=2, n=3333}]}
Process finished with exit code 0
一些意外收获:
在检查代码过程中,我偶然发现,注解@One和@Many的功能其实是一样的,刚开始我以为是巧合,但是我查看了源码,发现@One和@Many的源码也是一样的。我猜测,出现@one和@Many两种注解只是为了增加代码可读性。
我查看了mybatis的文档,有了以下的发现:
不管是一对一关联查询还是一对多关联查询:
- 都可以用@One或者@Many注解,二者效果一样。
- 如果映射到一个 JavaBean,还可以省略javaType属性,因为mybatis可以推断类型。但如果映射到的是 HashMap,那么应该指定javaType的属性。