2

I'm trying to call the child mapper method by a flexible case But in this case, we don't know which method will be called even it extends parent mapper. [spring boot framework with mybatis]

// ParentMapper
public interface ParentMapper
{
    // List<Map<String, String> findAll();
}

// Child1Mapper
public interface Child1Mapper extends ParentMapper
{
    List<Map<String, String> findAll();
}

// Child2Mapper
public interface Child2Mapper extends ParentMapper{
    List<Map<String, String> findAll();
}



@Autowired
Child1Mapper child1Mapper;

@Autowired
Child2Mapper child2Mapper;

// some class file
public ParentMapper getMapper(String param){
    switch(param){
        case "case1" : child1Mapper;
        case "case2" : child2Mapper;
        ... 10 more..
    }
}



public class example{
    public void somethid(){
        // this logic is in some biz
        ParentMapper mapper = getMapper("case1");  // <----`-` we do not know where `findAll method` located is in
        mapper.findAll();
    }
}

how to call the child mapper method

kokojustin
  • 190
  • 3
  • 12

4 Answers4

1

Its clear in code if you pass case1 to getMapper(String param) method it will return return new Child1Mapper() child1mapper object, so if you invoke findAll() method then child1mapper class findAll() method will be invoked

In case if you pass case2 then you will get child2mapper object (which is like Parentmapper p = new Child2Mapper()) so if you call findAll() method (p.findAll()) child2mapper findAll() method will be invoked

child1mapper and child2maper both are child classes of parentmapper but there is no relation ship between child1mapper and child2mapper so there is no concept of methods conflict

Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • yes this is called `RunTime Polymorphism` which is parent reference having child object , check this https://www.javatpoint.com/runtime-polymorphism-in-java (check bank example) – Ryuzaki L Aug 17 '18 at 02:26
0

Whatever you have done is absolutely fine.

Provided: you are referring to actual implementation classes and not interfaces here

case "case1" : return new Child1Mapper();
case "case2" : return new Child2Mapper();

Interesting to know: You just implemented a design pattern here. Your getMapper method represents Factory Method Pattern. These type of methods are absolutely valid as per the need.

More information on Factory Method Pattern: https://www.tutorialspoint.com/design_pattern/factory_pattern.htm

Amit Phaltankar
  • 3,341
  • 2
  • 20
  • 37
  • thank you for your information. Yes, your case we can use Factory method pattern then I can use finAll method but. this case ParentMapper interface doesn't have findAll method. specifically, this code are working on spring boot framework with mybatis. – kokojustin Aug 17 '18 at 04:22
  • @김승갑 Its a basic object oriented feature. Interfaces are just definitions and your have your child classes who will provide the actual implementation. – Amit Phaltankar Aug 17 '18 at 05:05
0

TLDR: You're missing the method signature in the ParentMapper

public interface ParentMapper
{
    List<Map<String, String>> findAll();
}

You'll need to specify the shared method signature for any classes that wants to implement the ParentMapper interface. The interface is the contract for the implementation.

This will obligate the Child1Mapper and Child2Mapper to supply the implementation details for that signature.

public interface ParentMapper
{
    List<Map<String, String>> findAll();
}

// Child1Mapper
public class Child1Mapper implements ParentMapper
{
    public List<Map<String, String>> findAll() { /* implementation */ }
}

// Child2Mapper
public class Child2Mapper implements ParentMapper{
    public List<Map<String, String>> findAll() { /* implementation */ }
}

ParentMapper mapper = getMapper("child1"); mapper.findAll() will use the Child1Mapper instance's implementation.

Considering that you are using Spring, you can adjust your factory method to return Spring Beans too. For example: (this will vary depending on how you wire your spring beans)

@Bean
Child1MapperBean() { return new Child1Mapper() }
@Bean
Child2MapperBean() { return new Child2Mapper() }

public ParentMapper getMapper(String param){
    switch(param){
       case "case1" : return Child1MapperBean();
       case "case2" : return Child2MapperBean();
    }
}
shinjw
  • 3,329
  • 3
  • 21
  • 42
0

I just figured out.... If ParentMapper, ChildMappers have same methods. it works well.

or we can think about reflection.. like this.

Mapper mapper = getMapperClass(name);
Method method = mapper.getClass().getMethod(mapperQueryId, Map.class);
return (List<Map<String, Object>>) method.invoke(mapper, params);
kokojustin
  • 190
  • 3
  • 12