1
votes

I have the following class, but Spring and MyBatis-Spring-Boot-Starter will not autowire my mapper.

When I run the request, I get the output from the println()

sourceMapper = null

Model

public class Source {       
    @Autowired
    public static SourceMapper sourceMapper;   #### Why isn't this set?

    public static Source findOrCreate(String url) {
        ...
        System.out.println("sourceMapper = " + sourceMapper);
        source = sourceMapper.findByHost(host);
        ...
    }

}

I followed the examples as closely as possible.

http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/

The other @Autowired Mappers in the main @Controller class that handles requests work, even though they are private.

This is the Mapper class

package ...mapper;

@Mapper
public interface SourceMapper {
  ...

I ran into this issue again with a new model and mapper. I tried to follow Why is my Spring @Autowired field null? and the code sample, but it was still null! I tried @Configurable, @Service, @Component.

Model
@Configurable
public class Domain {
    @Autowired
    private static DomainMapper domainMapper;

    public static void incrementCounter(String host) {
        ...
        Domain d = getDomainMapper().find(host, thisMonth);

    public static DomainMapper getDomainMapper() {
        return domainMapper;

    public static void setDomainMapper(DomainMapper domainMapper) {
        Domain.domainMapper = domainMapper;
Mapper
@Mapper
public interface DomainMapper {

MyBatis 3.4.5, MyBatis Spring 1.3.1, MyBatis Spring Boot Autoconfigure 1.3.1, MyBatis Spring Boot Starter 1.3.1

2

2 Answers

1
votes

I fixed it with

private static DomainMapper getDomainMapper() {
    // https://stackoverflow.com/a/52997701/148844
    if (domainMapper == null)
        domainMapper = MyApplication.getApplicationContext().getBean(DomainMapper.class);
    return domainMapper;

And

MyApplication
@Autowired // for AWS
private static ApplicationContext context;
// I believe this only runs during an embedded Tomcat with `mvn spring-boot:run`. 
// I don't believe it runs when deploying to Tomcat on AWS.
public static void main(String[] args) {
    context = SpringApplication.run(MyApplication.class, args);

But I don't like it!

0
votes

Spring will only try to inject a bean for you if another bean requires it.

Your class Source is just a normal class with bunch of static methods.

Hence it's not under creation control of Spring.

If you want to inject SourceMapper to your Source, you should mark Source with @Component or @Service so that the container will know it should create a bean of Source type for you and give you an instance of SourceMapper.

Moreover, the SourceMapper should be declared non-static, to prevent if a class access the variable before injected. And static field can be injected only if it use field setter injection.