Java 事务教程-测试回滚

Java 事务教程-测试回滚,java,spring,transactions,dao,jdbctemplate,Java,Spring,Transactions,Dao,Jdbctemplate,我试图学习如何在JavaSpring中使用事务。我是一名java新手,请耐心听我说:-)我试图实现的单元测试是测试: 如果引发运行时异常,则回滚 我遇到的问题是 java.lang.NullPointerException 好了,开始。。我删去了一些代码以帮助提高可读性 TutorialTest.java @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = AppConfig.class, loader=

我试图学习如何在JavaSpring中使用事务。我是一名java新手,请耐心听我说:-)我试图实现的单元测试是测试: 如果引发运行时异常,则回滚

我遇到的问题是 java.lang.NullPointerException

好了,开始。。我删去了一些代码以帮助提高可读性

TutorialTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class TutorialTest {

    @Autowired
    private Dao dao;


    @Test
    public void that_if_a_runtime_exception_is_thrown_transaction_rolledback(){

        User u = new User();
        u.setUsername("FAIL_TEST");
        u.setPhone("0161");
        u.setEmail("FAIL_TEST@gmail.com");
        //dao.addUser(u);  // -- this will insert if uncommented out so I know it works

        OuterService os  = new OuterService();
        os.addUserThrowError(u);

    }
}
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class OuterService {

    @Autowired
    private Dao dao;

    @Transactional
    public void addUserThrowError(User user) throws RuntimeException{

        dao.addUser(user);  // gives me a java.lang.NullPointerException?

        throw new RuntimeException("This should roll back DB entry");
    }

}
@Configuration
@EnableTransactionManagement
@ComponentScan(value = {"com.training.spring.tx.tutorial.dao",
                        "com.training.spring.tx.tutorial.service"})
public class AppConfig {

    public DataSource dataSource() {

        // Create a BasicDataSource object and configure database

        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost/spring_training_tx");
        dataSource.setUsername("training");
        dataSource.setPassword("training");

        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(){
        return new JdbcTemplate(transactionManager().getDataSource());
    }

}
OuterService.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class TutorialTest {

    @Autowired
    private Dao dao;


    @Test
    public void that_if_a_runtime_exception_is_thrown_transaction_rolledback(){

        User u = new User();
        u.setUsername("FAIL_TEST");
        u.setPhone("0161");
        u.setEmail("FAIL_TEST@gmail.com");
        //dao.addUser(u);  // -- this will insert if uncommented out so I know it works

        OuterService os  = new OuterService();
        os.addUserThrowError(u);

    }
}
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class OuterService {

    @Autowired
    private Dao dao;

    @Transactional
    public void addUserThrowError(User user) throws RuntimeException{

        dao.addUser(user);  // gives me a java.lang.NullPointerException?

        throw new RuntimeException("This should roll back DB entry");
    }

}
@Configuration
@EnableTransactionManagement
@ComponentScan(value = {"com.training.spring.tx.tutorial.dao",
                        "com.training.spring.tx.tutorial.service"})
public class AppConfig {

    public DataSource dataSource() {

        // Create a BasicDataSource object and configure database

        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost/spring_training_tx");
        dataSource.setUsername("training");
        dataSource.setPassword("training");

        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(){
        return new JdbcTemplate(transactionManager().getDataSource());
    }

}
豆子是在

AppConfig.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class TutorialTest {

    @Autowired
    private Dao dao;


    @Test
    public void that_if_a_runtime_exception_is_thrown_transaction_rolledback(){

        User u = new User();
        u.setUsername("FAIL_TEST");
        u.setPhone("0161");
        u.setEmail("FAIL_TEST@gmail.com");
        //dao.addUser(u);  // -- this will insert if uncommented out so I know it works

        OuterService os  = new OuterService();
        os.addUserThrowError(u);

    }
}
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class OuterService {

    @Autowired
    private Dao dao;

    @Transactional
    public void addUserThrowError(User user) throws RuntimeException{

        dao.addUser(user);  // gives me a java.lang.NullPointerException?

        throw new RuntimeException("This should roll back DB entry");
    }

}
@Configuration
@EnableTransactionManagement
@ComponentScan(value = {"com.training.spring.tx.tutorial.dao",
                        "com.training.spring.tx.tutorial.service"})
public class AppConfig {

    public DataSource dataSource() {

        // Create a BasicDataSource object and configure database

        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost/spring_training_tx");
        dataSource.setUsername("training");
        dataSource.setPassword("training");

        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(){
        return new JdbcTemplate(transactionManager().getDataSource());
    }

}

首先,引用

@ContextConfiguration
定义用于 确定如何加载和配置的
ApplicationContext
集成测试

考虑一下如何在
OuterService
上使用它。看起来对吗?
OuterService
是否用于加载和配置集成测试的
ApplicationCOntext
?除非我遗漏了一些重要的东西,否则答案是:不

那么什么是
OuterService
?这是一种服务。你好像想把它当豆子用。什么是豆子?bean是一个对象,其生命周期由Spring管理。这包括bean类的实例化、对象的初始化、后处理,最后是对象的销毁

如果像这样创建对象

OuterService os  = new OuterService();
那么春天就不在了。您创建了该对象,而Spring没有办法钩住它。因此,您不能期望Spring自动关联其字段

@Autowired
private Dao dao;
由于您尚未初始化该字段,它仍然是
null
,这会导致
NullPointerException

那么,我们如何获得一个由Spring管理的
OuterService
bean呢?您可以为
OuterService
声明
@Bean
方法,或者使用
@Component
或其任何专门化注释
OuterService
,并对其所在的包进行组件扫描。然后将该bean注入到使用它的任何其他bean中。比如说,

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class, loader=AnnotationConfigContextLoader.class)
public class TutorialTest {

    @Autowired
    private Dao dao;

    @Autowired
    private OuterService os;

然后可以直接使用该变量

Spring不参与
newouterservice()查看Javadoc。Spring有非常好的文档。
@ContextConfiguration
做什么?你如何在春季申报豆子?嗨,我已经更新了这个问题来帮助改进它。我还从标题中删除了spring。我已经包含了bean声明,答案非常简单:Spring不参与新的OuterService();因此不会将任何内容自动关联到该对象中。解释更长。阅读SpringIOC文档,它解释了所有这些。我已经看了文档,我还没有进一步弄清楚我需要做什么?从您的回复中,我想我需要将新的OuterService()与bean配置链接起来。上面的bean示例是XML格式的,我被告知要学习的不是。。