【发布时间】:2014-07-13 09:55:02
【问题描述】:
我第一次使用最新的 spring (4.0.4) 和 Hibernate (4.3.5) 和 spring-data-jpa (1.6.0),并且无法让存储库在 MySQL 表上工作写入或删除数据。它正在读取数据,但是当我尝试删除时,什么也没有发生。如果我使用 H2 数据库,一切正常,但是当我将数据源切换为 MySQL 服务器时,delete() 停止工作。
问题 1:为什么当我使用 MySQL 数据源时,CrudRepository 子类不能从我的表实体中删除行,但如果我使用 H2 数据源,它可以使用相同的代码?
如果我在我的 CrudRepository 子类中创建这样的函数,我可以删除数据:
public interface MyEntityRepository extends CrudRepository<MyEntity, Long> {
@Modifying
@Query("delete from MyEntity where entity_id = ?1")
void delete(Long entityId);
@Modifying
@Query("delete from StageTeacher")
void deleteAll();
}
我希望我错过了一些简单的东西。但是在我的单元测试类中,我有这个自动装配的存储库参考:
@Autowired
MyEntityRepository myEntityRepository;
当我使用 MySQL 数据源时,这些命令什么都不做(它们甚至不会出现运行时错误):
myEntityRepository.deleteAll();
myEntityRepository.delete(myEntity.getId());
这是 2 个数据源(H2 已被注释掉)和我使用此代码创建的实体管理器工厂:
@Bean
public EntityManagerFactory entityManagerFactory() throws SQLException {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://<host name>:3306/<schema name>");
dataSource.setUsername("<username>");
dataSource.setPassword("<password>");
/*
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
DriverManagerDataSource dataSource = builder.setType(EmbeddedDatabaseType.H2).build();
*/
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
// used when I have H2 enabled
//vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
Properties properties = new Properties();
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLMyISAMDialect");
factory.setJpaProperties(properties);
factory.setPackagesToScan("<package with table entity classes>");
factory.setDataSource(dataSource);
factory.afterPropertiesSet();
return factory.getObject();
}
编辑:我已将以下内容添加到我的 log4j.xml:
<logger name="org.hibernate">
<level value="DEBUG"/>
</logger>
<logger name="org.springframework.data">
<level value="DEBUG"/>
</logger>
当我在 Repository 子类中取消注释我的方法时,我会在控制台中得到这个:
DEBUG [main] IntegrationTests.delete(54) | >>>>>>>>>> delete all??
DEBUG [main] AbstractTransactionImpl.begin(160) | begin
DEBUG [main] LogicalConnectionImpl.obtainConnection(226) | Obtaining JDBC connection
DEBUG [main] LogicalConnectionImpl.obtainConnection(232) | Obtained JDBC connection
DEBUG [main] JdbcTransaction.doBegin(69) | initial autocommit status: true
DEBUG [main] JdbcTransaction.doBegin(71) | disabling autocommit
Hibernate: delete from stage_teacher
DEBUG [main] AbstractTransactionImpl.commit(175) | committing
DEBUG [main] JdbcTransaction.doCommit(113) | committed JDBC Connection
DEBUG [main] JdbcTransaction.releaseManagedConnection(126) | re-enabling autocommit
DEBUG [main] LogicalConnectionImpl.releaseConnection(246) | Releasing JDBC connection
DEBUG [main] LogicalConnectionImpl.releaseConnection(264) | Released JDBC connection
删除成功!
但是,如果我将存储库子类方法注释掉,我会在控制台中得到这个:
DEBUG [main] IntegrationTests.delete(54) | >>>>>>>>>> delete??
DEBUG [main] AbstractTransactionImpl.begin(160) | begin
DEBUG [main] LogicalConnectionImpl.obtainConnection(226) | Obtaining JDBC connection
DEBUG [main] LogicalConnectionImpl.obtainConnection(232) | Obtained JDBC connection
DEBUG [main] JdbcTransaction.doBegin(69) | initial autocommit status: true
DEBUG [main] JdbcTransaction.doBegin(71) | disabling autocommit
Hibernate: select stageteach0_.entity_id as entity_i1_0_0_, stageteach0_.active as active2_0_0_, stageteach0_.alias as alias3_0_0_, stageteach0_.allow_marketing_emails as allow_ma4_0_0_, stageteach0_.allow_password_resets as allow_pa5_0_0_, stageteach0_.console_setting_id as console_6_0_0_, stageteach0_.date_created as date_cre7_0_0_, stageteach0_.date_deactivated as date_dea8_0_0_, stageteach0_.date_modified as date_mod9_0_0_, stageteach0_.default_role_id as default10_0_0_, stageteach0_.district_teacher_id as distric11_0_0_, stageteach0_.email_address as email_a12_0_0_, stageteach0_.first_name as first_n13_0_0_, stageteach0_.first_name_localized as first_n14_0_0_, stageteach0_.iid as iid15_0_0_, stageteach0_.last_name as last_na16_0_0_, stageteach0_.last_name_localized as last_na17_0_0_, stageteach0_.main_teacher_id as main_te18_0_0_, stageteach0_.password as passwor19_0_0_, stageteach0_.pref_language_id as pref_la20_0_0_, stageteach0_.rest_id as rest_id21_0_0_, stageteach0_.salutation_id as salutat22_0_0_, stageteach0_.school_teacher_id as school_23_0_0_, stageteach0_.status_id as status_24_0_0_, stageteach0_.tcd as tcd25_0_0_, stageteach0_.teacher_type_id as teacher26_0_0_, stageteach0_.username as usernam27_0_0_ from stage_teacher stageteach0_ where stageteach0_.entity_id=?
DEBUG [main] ResultSetProcessorImpl.extractResults(127) | Starting ResultSet row #0
DEBUG [main] EntityReferenceInitializerImpl.resolveEntityKey(142) | On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified
DEBUG [main] TwoPhaseLoad.doInitializeEntity(160) | Resolving associations for [org.mind.gen40.domain.gen40.StageTeacher#10956]
DEBUG [main] TwoPhaseLoad.doInitializeEntity(286) | Done materializing entity [org.mind.gen40.domain.gen40.StageTeacher#10956]
DEBUG [main] AbstractLoadPlanBasedEntityLoader.load(208) | Done entity load : org.mind.gen40.domain.gen40.StageTeacher#10956
DEBUG [main] AbstractTransactionImpl.commit(175) | committing
DEBUG [main] JdbcTransaction.doCommit(113) | committed JDBC Connection
DEBUG [main] JdbcTransaction.releaseManagedConnection(126) | re-enabling autocommit
DEBUG [main] LogicalConnectionImpl.releaseConnection(246) | Releasing JDBC connection
DEBUG [main] LogicalConnectionImpl.releaseConnection(264) | Released JDBC connection
删除失败是否与此消息有关?
On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified
我不确定这意味着什么......
问题 2:我是否必须为每个需要基本 CRUD 操作的表子类 CrudRepository,或者我可以使用对表实体类的引用在运行时为给定的创建 CrudRepository桌子?
问题3:如果我需要在大量的CrudRepository子类上手动创建我的delete和insert方法,在MySQL中给定的表生成表实体和DAO或repository类有什么建议吗?强>
【问题讨论】:
-
“停止工作”具体是什么意思?你有任何例外吗?打开 Hibernate SQL 日志记录(
DEBUG级别)并发布它发出的实际 SQL 查询。 -
当我在 CrudRepository 子类中没有 delete() 和 deleteAll() 方法(每个都有如上所示的 Modifying 和 Query 注释)时,我没有遇到任何异常。如果没有我在存储库子类中的方法,当我运行单元测试时,SQL 根本不会运行删除行,但也没有异常或失败。
-
加快日志记录。某处会解释为什么它没有继续。
-
您使用的是什么日志系统?你是如何启动应用程序的?
-
我通过将其放入我的 log4j.xml 中记录了大量信息:
.. 。 谢谢!我正在尝试通过此排序以查看仅与删除尝试相关的日志记录。