mybatis双向多对一 报java.lang.StackOverflowError
java.lang.StackOverflowError at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:801) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:699) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:622) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) at org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory$EnhancedResultObjectProxyImpl.invoke(JavassistProxyFactory.java:163) at com.nwl.entity.User_$$_jvst8cb_1.toString(User_$$_jvst8cb_1.java) at java.base/java.lang.String.valueOf(String.java:2951) at com.nwl.entity.Pet.toString(Pet.java:43) at com.nwl.entity.Pet_$$_jvst8cb_0._d13toString(Pet_$$_jvst8cb_0.java) at jdk.internal.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory$EnhancedResultObjectProxyImpl.invoke(JavassistProxyFactory.java:161) at com.nwl.entity.Pet_$$_jvst8cb_0.toString(Pet_$$_jvst8cb_0.java) at java.base/java.lang.String.valueOf(String.java:2951) at java.base/java.lang.StringBuilder.append(StringBuilder.java:168) at java.base/java.util.AbstractCollection.toString(AbstractCollection.java:473) at java.base/java.lang.String.valueOf(String.java:2951) at com.nwl.entity.User.toString(User.java:45)
代码如下:
public class Pet {
private Integer id;
private String nickname;
private User user;
public Pet() {
}
public Pet(Integer id, String nickname, User user) {
this.id = id;
this.nickname = nickname;
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Pet{" +
"id=" + id +
", nickname='" + nickname + '\'' +
", user=" + user +
'}';
}
}
public class User {
private Integer id;
private String name;
private List<Pet> pets;
public User() {
}
public User(Integer id, String name, List<Pet> pets) {
this.id = id;
this.name = name;
this.pets = pets;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Pet> getPets() {
return pets;
}
public void setPets(List<Pet> pets) {
this.pets = pets;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pets=" + pets +
'}';
}
}
public interface PetMapper {
List<Pet> queryByUserId(Integer userId);
Pet queryById(Integer id);
}
PetMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nwl.mapper.PetMapper">
<resultMap id="PetResultMap" type="Pet">
<id property="id" column="id"/>
<result property="nickname" column="nickname"/>
<association property="user" column="user_id" select="com.nwl.mapper.UserMapper.queryById"/>
</resultMap>
<select id="queryById" parameterType="integer" resultMap="PetResultMap">
select * from mybatis_pet where id=#{id}
</select>
<select id="queryByUserId" parameterType="integer" resultMap="PetResultMap">
select * from mybatis_pet where user_id=#{userId}
</select>
</mapper>
public interface UserMapper {
User queryById(Integer id);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nwl.mapper.UserMapper">
<resultMap id="userResultMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- <collection>表示这个映射是一个集合属性
ofType="Pet"表示这个集合是Pet类型的
column="id"表示 select * from mybatis_user from id=#{id}的id
select="com.nwl.mapper.PetMapper.queryByUserId"表示调用此方法返回该用户的所有pet-->
<collection property="pets" ofType="Pet" column="id"
select="com.nwl.mapper.PetMapper.queryByUserId"/>
</resultMap>
<select id="queryById" parameterType="Integer" resultMap="userResultMap">
select * from mybatis_user where id=#{id}
</select>
</mapper>
@Test
public void test4(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println(mapper.queryById(1));
}
@Test
public void test5(){
PetMapper mapper = sqlSession.getMapper(PetMapper.class);
System.out.println(mapper.queryById(1));
}
原因是Pet类的toString方法有User对象,User类的toString方法有Pet对象,如果直接使用toString方法输出对象会形成死循环,所以会报这个错,要想不报错可以单独输出对象的属性
@Test
public void test4(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryById(1);
System.out.println(user.getName()+"的宠物有:");
for (Pet pet:user.getPets()){
System.out.println(pet.getNickname());
}
}
@Test
public void test5(){
PetMapper mapper = sqlSession.getMapper(PetMapper.class);
Pet pet = mapper.queryById(1);
System.out.println(pet.getNickname()+":"+pet.getUser().getName());
}

浙公网安备 33010602011771号