h2数据库上的Mybatis无法插入数据
Mybatis on h2 database can't insert data
我正在使用 spring boot v1.4.1.RELEASE
+ mybatis-spring-boot-starter v1.1.1
+ h2database v1.4.192
+ flywaydb v4.0.3
构建一个 spring 引导 Web 应用程序。
这是我的 yml 配置部分文件或数据源配置:
数据源:
公里:
driverClassName: org.h2.Driver
url:jdbc:h2:mem:km;模式=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.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)
这是我尝试过的解决方案:
- 将 yml 文件中的数据源配置从
url: jdbc:h2:mem:km;MODE=MySQL
更改为 url: jdbc:h2:mem:km;MODE=MySQL;LOCK_MODE=1
。不工作。
- 从 ut 代码中删除
@Transactional
和 @Rollback
注释。不工作。
接下来我该怎么做才能解决这个问题?
@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;
}
我的代码中有一些错误:
@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。所以,我无法得到正确的值。当我删除这一行时,这个单元测试就通过了。
我正在使用 spring boot v1.4.1.RELEASE
+ mybatis-spring-boot-starter v1.1.1
+ h2database v1.4.192
+ flywaydb v4.0.3
构建一个 spring 引导 Web 应用程序。
这是我的 yml 配置部分文件或数据源配置:
数据源:
公里:
driverClassName: org.h2.Driver
url:jdbc:h2:mem:km;模式=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.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)
这是我尝试过的解决方案:
- 将 yml 文件中的数据源配置从
url: jdbc:h2:mem:km;MODE=MySQL
更改为url: jdbc:h2:mem:km;MODE=MySQL;LOCK_MODE=1
。不工作。 - 从 ut 代码中删除
@Transactional
和@Rollback
注释。不工作。
接下来我该怎么做才能解决这个问题?
@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;
}
我的代码中有一些错误:
@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。所以,我无法得到正确的值。当我删除这一行时,这个单元测试就通过了。