【问题标题】:@Transactional not working with readOnly = true@Transactional 不适用于 readOnly = true
【发布时间】:2013-11-26 12:54:40
【问题描述】:

我有以下代码,我在其中设置@Transactional(readOnly = true)。

main() 方法中的代码:

    ApplicationContext context = Utils.getContext();
    AnnotatedCrudDao service = new AnnotatedCrudDao();
    DataSource dataSource = (DataSource) context.getBean("mySqlDataSource");
    service.setDataSource(dataSource);
    service.insert(account, user, movie);


@Transactional
public class AnnotatedCrudDao extends JdbcDaoSupport {

    private static Logger logger;

    static {
    logger = Logger.getLogger(AnnotatedCrudDao.class);
    }


    @Transactional(readOnly = true)
    public void insert(Account account, User user, MovieTicket movie) {

    TicketUtils.insertAccount(getJdbcTemplate(), account);
    TicketUtils.insertUser(getJdbcTemplate(), user);
    TicketUtils.insertMovie(getJdbcTemplate(), movie);
    }
}

class TicketUtils{

    public static void insertUser(JdbcTemplate template, User user) {
    String queryUser = "INSERT INTO t_user_txn (ID, NAME, ACCOUNT_ID, TICKETID) VALUES (?,?,?,?)";
    logger.debug("queryUser" + queryUser);
    template.update(queryUser, new Object[] { user.getId(), user.getName(),
    user.getAccount().getId(), user.getTicketId() });
    }

    public static void insertMovie(JdbcTemplate template, MovieTicket movie) {
    String queryMovie = "INSERT INTO t_movieticket_txn (ID, MOVIENAME, TOTALTICKETSCOUNT, PRICE) VALUES (?,?,?,?)";
    logger.debug("queryMovie:" + queryMovie);
    template.update(queryMovie, new Object[] { movie.getId(),
    movie.getMovieName(), movie.getTotalTicketsCount(),
    movie.getPrice() });
    }

    public static void insertAccount(JdbcTemplate template, Account account) {
    String queryAccount = "INSERT INTO t_account_txn (ID, AMOUNT) VALUES (?,?)";
    logger.debug("queryAccount:" + queryAccount);
    template.update(queryAccount, new Object[] { account.getId(),
    account.getAmount() });
    }

}

上下文:

    <bean id="mySqlDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:qadb7"/>
    <property name="username" value="tp2"/>
    <property name="password" value="tp2"/>
    </bean>

    <bean id="dsTxnMgr" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="mySqlDataSource" />
    </bean>

    <!-- Add this tag to enable annotations transactions -->
    <tx:annotation-driven transaction-manager="dsTxnMgr" />

即使我已经为插入方法设置了@Transactional(readOnly = true),但插入操作仍在执行中。属性readOnly 不应该设置为true 应该注意不能在此方法上执行插入。

【问题讨论】:

标签: java spring transactions


【解决方案1】:

几件事

  1. 您正在创建自己的 dao 实例,这不是 spring 管理的,因此 @Transactional 注释没有做任何事情。
  2. readonly="true" 不强制执行任何操作,不要期望抛出异常或不发生插入,很少有 jdbc 提供程序实际上使用 readOnly 标志做某事。它只是对底层系统的提示而已。通常,它被 Hibernate 等 ORM 工具使用和理解。但在大多数情况下,对于普通的 JDBC 访问,它会被忽略。

【讨论】:

    【解决方案2】:

    您需要放置一个@Repository 注释才能使其正常工作

    @Transactional
    @Repository
    public class AnnotatedCrudDao extends JdbcDaoSupport {
    

    【讨论】:

    • 确保添加包扫描以将 bean 包含到应用程序上下文中。
    【解决方案3】:

    您正在自己创建AnnotatedCrudDao 对象。因此,Spring 无法处理它并添加 @Transactional 行为。

    AnnotatedCrudDao service = new AnnotatedCrudDao();
    

    让 Spring 管理您的对象。在你的上下文中为它声明一个 &lt;bean&gt; 元素并使用它。

    【讨论】:

      猜你喜欢
      • 2020-08-15
      • 1970-01-01
      • 2017-06-06
      • 1970-01-01
      • 2017-11-08
      • 1970-01-01
      • 1970-01-01
      • 2020-05-16
      • 2017-12-12
      相关资源
      最近更新 更多