简体   繁体   English

无法在CrudRepository上使用delete()

[英]Cannot use delete() on CrudRepository

I'm using the latest spring (4.0.4) and Hibernate (4.3.5) and spring-data-jpa (1.6.0) for the first time and am having trouble getting the repository to work on a MySQL table to write or delete data. 我第一次使用最新的spring(4.0.4)和Hibernate(4.3.5)和spring-data-jpa(1.6.0),但在使存储库在MySQL表上工作以进行写入或写入时遇到麻烦删除数据。 It's reading data fine, but when I try to delete, nothing happens. 它读取数据很好,但是当我尝试删除时,什么也没发生。 Things work fine if I use an H2 database, but when I switch my data source to be a MySQL server, delete() stops working. 如果使用H2数据库,一切正常,但是当我将数据源切换为MySQL服务器时,delete()停止工作。

Question 1: Why isn't the CrudRepository sub-class able to delete rows from my table entity when I use a MySQL data source, but it works with the same code if I use an H2 data source? 问题1:当我使用MySQL数据源时,为什么CrudRepository子类不能从表实体中删除行,但是如果使用H2数据源,它就可以使用相同的代码工作?

I can delete data if I create functions like this in my sub-class of CrudRepository: 如果在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();
}

I am hoping I'm missing something simple. 我希望我缺少一些简单的东西。 But in my unit test class, I've got this autowired repository reference: 但是在我的单元测试课中,我得到了这个自动装配的存储库参考:

@Autowired
MyEntityRepository myEntityRepository;

When I'm using the MySQL data source these commands do nothing (they don't even case a run-time error): 当我使用MySQL数据源时,这些命令不执行任何操作(它们甚至不会出现运行时错误):

myEntityRepository.deleteAll();
myEntityRepository.delete(myEntity.getId());

Here's the 2 data sources (H2 is commented out) and the entity manager factory I create using this code: 这是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();
}

EDIT: I've added the following to my log4j.xml: 编辑:我已经将以下内容添加到我的log4j.xml中:

<logger name="org.hibernate">
    <level value="DEBUG"/>
</logger>
<logger name="org.springframework.data">
    <level value="DEBUG"/>
</logger>

I get this in the console when I have my methods un-commented in the Repository sub-class: 当我的方法在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

and the delete succeeds! 删除成功!

However, if I comment the repository sub-class methods out, I'll get this in the console: 但是,如果我注释掉存储库子类方法,则将在控制台中得到它:

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

Does the failure to delete have something to do with this message? 删除失败与此消息有关吗?

On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified

I'm not sure what that means... 我不确定这意味着什么...

Question 2: Do I have to sub-class CrudRepository for each table that I need basic CRUD operations on, or can I use a reference to the table entity class to create a CrudRepository at run-time for a given table? 问题2:我是否必须为需要基本CRUD操作的每个表创建CrudRepository的子类,还是可以在运行时为给定表使用对表实体类的引用来创建CrudRepository?

Question 3: If I need to manually create my delete and insert methods on a large number of CrudRepository sub-classes, are there any suggestions on generating table entities and DAO or repository classes given tables in MySQL? 问题3:如果需要在大量CrudRepository子类上手动创建删除和插入方法,那么在生成表实体和DAO或MySQL中给定表的存储库类方面是否有任何建议?

I've discovered that the problem was rooted in the fact that I was running my code using a unit test. 我发现问题根源在于我正在使用单元测试运行代码。 Apparently unit tests are setup as transactions that are automatically rolled back, but I can't find documentation to support that. 显然,单元测试被设置为自动回滚的事务,但是我找不到支持它的文档。 My unit test was creating a row in a table and then deleting the row based on it's ID. 我的单元测试是在表中创建一行,然后根据其ID删除该行。 It was always failing because it was always rolling back the transaction. 它总是失败,因为它总是回滚事务。

If you need unit tests that actually do a delete then add the rollback(false) annotation so your unit test method looks like this: 如果您需要实际执行删除的单元测试,请添加rollback(false)批注,以便您的单元测试方法如下所示:

@Autowired
MyEntityRepository myEntityRepository;

@Test
@Rollback(false)
public void createAndThenDeleteRow() {
    MyEntity testRecord = new TestRecord( "fake", "data" );
    TestRecord savedRecord = myEntityRepository.save( testRecord );
    Long id = savedRecord.getId();
    TestRecord loadedRecord = myEntityRepository.findOne( id );
    assertNotNull( loadedRecord );
    myEntityRepository.delete( id );
    TestRecord reloadedRecord = myEntityRepository.findOne( id );
    assertNull( reloadedRecord );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM