spring整合mybatis的一个转账业务

spring整合mybatis的一个转账业务

报错信息

img

整体结构

img

AccountMapper


```java
package com.fei.bank.mapper;

import com.fei.bank.pojo.Account;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface AccountMapper {

    /**
     * 新增账户
     * @param account
     * @return
     */
    int insert(Account account);

    /**
     * 根据账号删除账户
     * @param actno
     * @return
     */
    int deleteByActno(String actno);

    /**
     * 更新账户
     * @param account
     * @return
     */
    int update(Account account);

    /**
     * 根据账号查询账户
     * @param actno
     * @return
     */
    Account selectByActno(String actno);

    /**
     * 查询所有账户
     * @return
     */
    List selectAll();
}

Account

package com.fei.bank.pojo;

/**
 * 账户类
 */
public class Account {
    private String actno;
    private Double balance;

    @Override
    public String toString() {
        return "Account{" +
                "actno='" + actno + '\'' +
                ", balance=" + balance +
                '}';
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }

    public Account(String actno, Double balance) {
        this.actno = actno;
        this.balance = balance;
    }

    public Account() {
    }
}

AccountService

package com.fei.bank.service;

import com.fei.bank.pojo.Account;
import org.springframework.stereotype.Service;

import java.util.List;


public interface AccountService {

    /**
     * 开户
     * @param account
     * @return
     */
    int save(Account account);

    /**
     * 销户
     * @param actno
     * @return
     */
    int deleteByActno(String actno);

    /**
     * 修改账户信息
     * @param account
     * @return
     */
    int modify(Account account);

    /**
     * 查询账户
     * @param actno
     * @return
     */
    Account getByActno(String actno);

    /**
     * 查询所有账户
     * @return
     */
    List getAll();

    /**
     * 转账
     * @param fromActno
     * @param toActno
     * @param money
     */
    void transfer(String fromActno,String toActno,double money);

}


AccountServiceImpl

package com.fei.bank.service.impl;

import com.fei.bank.mapper.AccountMapper;
import com.fei.bank.pojo.Account;
import com.fei.bank.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.annotation.Resources;
import java.util.List;


@Transactional
@Service("accountService")
public class AccountServiceImpl implements AccountService {

    @Resource(name = "accountMapper")
    private AccountMapper accountMapper;

    @Override
    public int save(Account account) {
        return accountMapper.insert(account);
    }

    @Override
    public int deleteByActno(String actno) {
        return accountMapper.deleteByActno(actno);
    }

    @Override
    public int modify(Account account) {
        return accountMapper.update(account);
    }

    @Override
    public Account getByActno(String actno) {
        return accountMapper.selectByActno(actno);
    }

    @Override
    public List getAll() {
        return accountMapper.selectAll();
    }

    @Override
    public void transfer(String fromActno, String toActno, double money) {
        Account fromAct = accountMapper.selectByActno(fromActno);
        if (fromAct.getBalance() < money){
            throw new RuntimeException("余额不足");
        }
        Account toAct = accountMapper.selectByActno(toActno);
        fromAct.setBalance(fromAct.getBalance() - money);
        toAct.setBalance(toAct.getBalance() + money);
        int count = accountMapper.update(fromAct);
        count += accountMapper.update(toAct);
        if (count != 2){
            throw new RuntimeException("转账失败");
        }
    }
}


AccountMapper.xml


mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fei.bank.mapper.AccountMapper">
    
    <insert id="insert">
        insert into t_act values(#{actno},#{balance})
    insert>

    <delete id="deleteByActno">
        delete from t_act where actno = #{actno}
    delete>
    
    <update id="update">
        update t_act set actno = #{actno}, balance = #{balance}
    update>

    <select id="selectByActno" resultType="Account">
        select * from t_act where actno = #{actno}
    select>

    <select id="selectAll" resultType="Account">
        select * from t_act
    select>
mapper>


jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db1
jdbc.username=root
jdbc.password=541366

spring.xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    
    <context:component-scan base-package="com.fei.bank"/>

    
    <context:property-placeholder location="jdbc.properties"/>

    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    bean>

    
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        
        <property name="dataSource" ref="dataSource"/>
        
        <property name="configLocation" value="mybatis-config.xml"/>
        
        <property name="typeAliasesPackage" value="com.fei.bank.pojo"/>
    bean>

    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.fei.bank.mapper"/>
    bean>

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

    
    <tx:annotation-driven transaction-manager="txManager"/>
beans>


TransferTest

package com.fei.bank.test;

import com.fei.bank.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TransferTest {

    @Test
    public void testTransfer(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
        try {
            accountService.transfer("act001","act002",10000);
            System.out.println("转账成功");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}


50行,是这里吧, 很明显这里判断异常了, 你断点一看就知道是什么问题

img

你的AcountServiceImpl第50行报了一个空指针

该回答引用GPTᴼᴾᴱᴺᴬᴵ
根据您提供的信息,很难确定导致问题的具体原因。但是,根据错误消息中提供的信息,可以看出问题发生在调用 AccountServiceImpl.transfer 方法时,该方法在执行过程中调用了一些其他的方法。这些方法的实现可能存在一些问题导致整个事务失败。

建议您可以通过以下方式来排查问题:

  1. 检查数据库连接和配置信息是否正确。
  2. 确保 MyBatis 映射文件和实体类的映射关系正确,以及 SQL 语句的正确性。
  3. 检查是否存在事务配置问题。可能需要配置事务管理器、声明式事务等。
  4. 确保应用程序的依赖库版本正确。
  5. 在代码中增加必要的日志输出,以便更好地跟踪问题。

如果您能提供更详细的错误信息和代码,我们可以更好地帮助您排查问题。