Mybatis в базе данных h2 не может вставить данные

#spring-boot #h2 #mybatis

#весенняя загрузка #h2 #mybatis

Вопрос:

Я использую spring boot v1.4.1.RELEASE mybatis-spring-boot-starter v1.1.1 h2database v1.4.192 flywaydb v4.0.3 для создания веб-приложения spring boot.

вот мой файл части конфигурации yml или конфигурация источника данных:


datasource:
km: 

driverClassName: org.h2.Driver

url: jdbc:h2:mem:km;MODE=MySQL;

И, когда я использую mysql для запуска моего модульного теста, каждый модульный тест был пройден. Но, когда я переключаюсь на базу данных h2database, тот же тест не был пройден.

Код ut приведен ниже:

 @RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = App.class)
@ActiveProfiles("unit-test")
@Transactional
@Rollback
public class FollowServiceTest {
    private int HOST_ID = 1;
    private int UID = 100;

    @Autowired
    private FollowService followService;

    @Autowired
    private UserFollowDAO followDAO;

    @Test
    public void testFans() throws Exception {

        UserFollow userFollow = new UserFollow();
        userFollow.setHostId(HOST_ID);
        userFollow.setFollowerId(UID);
        followDAO.insert(userFollow);

        List<UserFollow> fans = followDAO.findByIndexHostId(HOST_ID, 0, 10);

        assertThat("fans is empty", fans, not(empty()));
    }
}
  

UserFollowDAO:

 public interface UserFollowDAO {
    public static final String COL_ALL = " id, host_id, follower_id, create_time, last_update_time "; 
    public static final String TABLE = " user_follow "; 


    @Select(" select "  
            COL_ALL  
            " from "  
            TABLE  
            " where "  
            "`host_id` = #{hostId} "  
            " and id > #{lastId} "  
            " limit #{count} "
    )
    public List<UserFollow> findByIndexHostId(
            @Param("hostId") int hostId,
            @Param("lastId") int lastId,
            @Param("count") int count
    );

    @Insert(" insert into "   TABLE   " set "
          " id = #{id}, "
          " host_id = #{hostId}, "
          " follower_id = #{followerId}, "
          " create_time = now(), "
          " last_update_time = now()")
    public int insert(UserFollow bean);
}
  

Информация об ошибке:

 java.lang.AssertionError: fans is empty
Expected: not an empty collection
     but: was <[]>

    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.junit.Assert.assertThat(Assert.java:956)
    at com.hi.hk.api.service.FollowServiceTest.testFans(FollowServiceTest.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  

Here is my solutions that I have try:

  1. Change datasource config in yml file from url: jdbc:h2:mem:km;MODE=MySQL to url: jdbc:h2:mem:km;MODE=MySQL;LOCK_MODE=1 . Not work.
  2. Delete @Transactional and @Rollback annotation from ut code. Not work.

What can I do next to solve this problem?

@pau:

Here is part of my application-unit-test.yml config file:


datasource:
ut: true
km: 

driverClassName: org.h2.Driver

url: jdbc:h2:mem:km;MODE=MySQL

И я изменил конфигурацию источника данных, как вы сказали:

 @Value("${datasource.ut}")
private boolean isUt;

public static final String SQL_SESSION_FACTORY_NAME = "sessionFactoryKm";
public static final String TX_MANAGER = "txManagerKm";
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

@Bean(name = "datasourceKm")
@Primary
@ConfigurationProperties(prefix = "datasource.km")
public DataSource dataSourceKm() {
    if (isUt){
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        return builder.setType(EmbeddedDatabaseType.H2).build();
        // Because I am use migration db to execute init sql script, so I haven't set script.
    }
    return DataSourceBuilder.create().build();
}
  

Вот flyway компонент:

 @Bean(name = "KmMigration", initMethod = "migrate")
@Primary
public Flyway flyway() throws SQLException {
    logger.info(("================= start km db migration ================="));
    Flyway flyway = new Flyway();
    flyway.setDataSource(dataSourceKm());
    flyway.setBaselineOnMigrate(true);

    if (flyway.getDataSource().getConnection().getMetaData().getDatabaseProductName().toString().contains("H2")) {
        logger.info(("================= using h2 database to start this app ================="));
        flyway.setLocations("/db/migration/ut/km");
    } else {
        flyway.setLocations("/db/migration/km");
    }

    // different developer environment. might get different checksum,
    //   add the statement to skip the checksum error
    // TODO: Maintain checksum across all developers environment.
    flyway.setValidateOnMigrate(false);
    MigrationVersion baselineVersion = flyway.getBaselineVersion();
    logger.info(baselineVersion.getVersion());

    return flyway;
}
  

Ответ №1:

В mycode есть какая-то ошибка:

 @Insert(" insert into "   TABLE   " set "
          " id = #{id}, "// this line
          " host_id = #{hostId}, "
          " follower_id = #{followerId}, "
          " create_time = now(), "
          " last_update_time = now()")
    public int insert(UserFollow bean);
  

Этот метод insert будет использовать значение id в bean, то есть 0. Таким образом, я не могу получить правильное значение. когда я удаляю эту строку, модульный тест пройден.