h2数据库上的Mybatis无法插入数据

时间:2016-10-25 03:40:22

标签: spring-boot h2 mybatis

我使用spring boot v1.4.1.RELEASE + mybatis-spring-boot-starter v1.1.1 + h2database v1.4.192 + flywaydb v4.0.3来构建Spring启动Web应用程序。

这是我的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)

以下是我尝试过的解决方案:

  1. 将yml文件中的数据源配置从url: jdbc:h2:mem:km;MODE=MySQL更改为url: jdbc:h2:mem:km;MODE=MySQL;LOCK_MODE=1。不行。
  2. 从ut代码中删除@Transactional@Rollback注释。不行。
  3. 我可以做些什么来解决这个问题?

    @pau:

    以下是我的application-unit-test.yml配置文件的一部分:

    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:

    @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 个答案:

答案 0 :(得分:0)

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方法将在bean中使用id的值,即0.因此,我无法获得正确的值。当我删除这一行时,将通过此单元测试。