微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

有没有更好的方法来使用 Java Spring Boot 和 JPA 编写这个练习?

如何解决有没有更好的方法来使用 Java Spring Boot 和 JPA 编写这个练习?

我正在从我的 Spring Boot 课程中构建作业,到目前为止我做了 JPA 层并希望在开始业务规则之前获得一些反馈,关于我是否可以改进某些东西或改变我的关系类型应用程序。 任何建议都会受到欢迎。

这是练习:

“假设我们有一个很大的遗留系统,其中一个部分是提款处理(允许将资金从公司转移到员工账户的过程)。现在我们有机会完全重写系统,包括 API 更改(端点、 DTO 等)作为技术挑战,我们建议您接受它。您可以按照验收标准做任何想做的事情:

  • 使用您喜欢的任何架构
  • 使用现代 Java 或 Kotlin
  • 使用 Spring Boot
  • 使用任何数据库 sql/Nosql(请使用嵌入式)
  • 必须对代码进行测试
  • 服务应该易于运行(例如 docker-compose)

以下是处理的一些业务规则:

  • 我们有一个用户列表(/v1/users 端点)
  • 一个用户有多种付款方式
  • 用户可以使用其中一种付款方式执行提款请求
  • 提款可以尽快执行或安排稍后执行
  • 服务收到请求后,它会在我们的数据库中存储一个取款对象,并向支付提供商异步发送请求。注意:对于此任务,我们不关心事务完成
  • 我们必须 100% 发送有关任何提款状态(事件、电子邮件等)的通知

这是我对带有 JPA 的模型的解决方案:

  • 用户

     @Entity(name = "User")
     @Table(name = "user",uniqueConstraints = {@UniqueConstraint(name= "user_email_unique",columnNames = 
     "email")})
     public class User {
    
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Column(name = "user_id",updatable=false)
     private Long id;
    
     @OnetoMany(mappedBy="user")
     @Column(name = "payment_methods")
     private List<PaymentMethod> paymentMethods;
    
     @OnetoOne(mappedBy = "user")
     @JoinColumn(name = "account_id",nullable = false)
     private Account account;
    
     @Column(name = "first_name",nullable = false,columnDeFinition = "TEXT")
     private String firstName;
    
     @Column(name = "last_name",columnDeFinition = "TEXT")
     private String lastName;
    
     @Column(name = "email",nullable = false)
     private String email;
    
     @Column(name = "max_withdrawal_amount",columnDeFinition = "DOUBLE")
     private Double maxWithdrawalamount;
    
    }
    
  • 账户:

    @Entity(name = "Account")
    @Table(name = "account",uniqueConstraints = {
    @UniqueConstraint(name = "account_account_number_unique",columnNames = "account_number") })
    public class Account {
    
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Column(name = "account_id")
     private Long id;
    
     @OnetoOne(fetch = FetchType.LAZY)
     @MapsId
     private User user;
    
     @OnetoMany(mappedBy = "account",cascade = CascadeType.ALL,fetch = FetchType.EAGER)
     private List<Transaction> transactionList = new ArrayList<>();
    
     @Column(name = "account_number",nullable = false)
     private Integer accountNumber;
    
     @Column(name = "balance",nullable = false)
     private double balance;
    

    }

  • 付款方式

    @Entity(name = "PaymentMethod")
    @Table(name = "payment_methods")
    public class PaymentMethod {
    
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Column(name = "payment_methods_id")
     private Long id;
    
     @ManyToOne
     @JsonIgnore
     @JoinColumn(name = "user_id",nullable = false)
     private User user;
    
     @Column(name = "payment_name",columnDeFinition = "TEXT")
     private String paymentName;
    

    }

  • 交易

    @Entity(name = "Transaction")
    @Table(name = "transaction")
    public class Transaction {
    
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Column(name = "transaction_id",updatable = false)
     private Long id;
    
     @Column(name = "comment",columnDeFinition = "TEXT")
     private String comment;
    
     @ManyToOne
     @JoinColumn(name = "accountNumber")
     private Account account;
    

    }

  • 提款

    @Entity(name = "Withdrawal")
    @Table(name = "withdrawal")
    public class Withdrawal {
    
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Column(name = "withdrawals_id")
     private Long id;
    
     @OnetoOne(fetch = FetchType.LAZY)
     @MapsId
     private Transaction transaction;
    
     @ManyToOne
     @JsonIgnore
     @JoinColumn(name = "payment_methods_id",nullable = false)
     private PaymentMethod paymentMethod;
    
     @Column(name = "amount",columnDeFinition = "DOUBLE")
     private Double amount;
    
     @Column(name = "created_at",columnDeFinition = "DATE DEFAULT CURRENT_DATE")
     private Instant createdAt;
    
     @Column(name = "execute_at",columnDeFinition = "DATE DEFAULT CURRENT_DATE")
     private Instant executeAt;
    
     @Enumerated(EnumType.STRING)
     @Column(name = "withdrawal_status",columnDeFinition = "TEXT")
     private WithdrawalStatus status;
    

    }

解决方法

看起来已经很安静了。我有一些建议。

  • 您将 Amounts 存储在 Double 中,这可能会导致计算时出现问题。通常的做法是使用以美分为单位的数量并使用整数/长,这样您就不会遇到这些问题。 java afaik 中还有一个货币类。

  • 提款难道不是从一个账户到另一个账户的交易吗?为什么你甚至需要 Withdrawal 类? PaymentMethod、Amount 等也可以在交易中。我知道它说明了任务中的提款和交易,但从设计的角度考虑它是否有意义

  • 在 PaymentMethod 类中,PaymentName 可以是一个 Enum,所以它不是一个自由文本,而是一个定义好的支付提供商,很容易进行 switch/case on

,

我会按照其他用户的要求在 Stack Exchange 上发帖。非常感谢您的帮助,这篇文章就到此为止。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?