hehongwei44 / my-blog

我的博客
MIT License
137 stars 12 forks source link

MyBatis异常-Mapper中错误No constructor found... #150

Open hehongwei44 opened 7 years ago

hehongwei44 commented 7 years ago

业务模型如下:

package com.test.dao;

public class User {

    private int id;
    private String name;
    private int age;

    public User(int id, String name, int age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
}

在JUnit中写了一个测试程序,用来查询。

@Test
public void testSelect() {
    SqlSessionFactory factory = MyBatisUtils.getFactory();
    SqlSession openSession = factory.openSession();
    UserMapper mapper = openSession.getMapper(UserMapper.class);
    User selectUser = mapper.selectUser(1);
    System.out.println(selectUser);
}

错误堆栈如下所示:

org.apache.ibatis.exceptions.PersistenceException: 

### Error querying database. Cause: org.apache.ibatis.executor.ExecutorException: No constructor found in com.tszhao.dao.User matching [java.lang.Integer, java.lang.String, java.lang.Integer]
### The error may exist in com/tszhao/mapper/UserMapper.java (best guess)
### The error may involve com.tszhao.mapper.UserMapper.selectUser
### The error occurred while handling results
### SQL: select * from users where id=?
### Cause: org.apache.ibatis.executor.ExecutorException: No constructor found in com.tszhao.dao.User matching [java.lang.Integer, java.lang.String, java.lang.Integer]
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
...

看样子,应该跟构造函数相关。找不到与User相关的构造函数。试着在User中增加了一个默认的构造函数,通过测试,所以千万不要忘了添加默认的构造函数。

hehongwei44 commented 7 years ago

具体原理不太清楚 黑人问号???

toastsgithub commented 7 years ago

我也遇到了同样的问题

你显式指定了构造函数之后,Java不会自动生成默认的构造函数,所以只能通过你的public User(int id, String name, int age)构造函数来实例化

然而resultMap不认int double之类的Java原始类型,只承认jdbcType里写的那个包装类型(Double,Integer),因为是第一次用这类数据库框架,所以具体原因还不太清楚,先Mark


猜想大体上实例化流程就是,resultMap会去调用Bean的默认构造函数,然后将所有的成员变量和查询结果的列名形成映射,当你显示地指定了一个构造函数,然而它又不能将查询结果和显示指定的构造函数的参数形成映射的时候就会抛出异常

No constructor found in com.tszhao.dao.User matching [java.lang.Integer, java.lang.String, java.lang.Integer]

(它想找的是传入Integer的构造函数, 而你只有传入int的构造函数)

所以要么不显式地指定构造函数,使用自动生成的默认构造函数

要么在自己指定的构造函数中使用包装类型

(当然也可以直接在你的那行构造函数上面显示地添加一个无参构造函数,不过看起来好像是多此一举)