Java 用于插入和删除域对象的数据库接口API的设计

Java 用于插入和删除域对象的数据库接口API的设计,java,oop,design-patterns,single-responsibility-principle,object-oriented-analysis,Java,Oop,Design Patterns,Single Responsibility Principle,Object Oriented Analysis,我正在尝试创建一个好的OOP设计,特别是符合SRP的,用于与数据库接口以插入和删除Customers。我的重点是设计,而不是被SQL和JDBC或数据源的细节所困扰。所以我留下了使用打印行的简单实现。但我想知道springs jdbctemplate是否就是这样设计的 这项工作是在我学习SRP OOP设计原则时完成的。设计不良的Customer类违反了SRP,因为它包含数据库插入/删除责任。我从Customer类中取出代码,并将其放入一个类中,该类继承自RdbmsManager基类,基类的职责是建

我正在尝试创建一个好的OOP设计,特别是符合SRP的,用于与数据库接口以插入和删除
Customer
s。我的重点是设计,而不是被SQL和JDBC或数据源的细节所困扰。所以我留下了使用打印行的简单实现。但我想知道springs jdbctemplate是否就是这样设计的

这项工作是在我学习SRP OOP设计原则时完成的。设计不良的
Customer
类违反了SRP,因为它包含数据库插入/删除责任。我从
Customer
类中取出代码,并将其放入一个类中,该类继承自
RdbmsManager
基类,基类的职责是建立连接并与数据库交互。我不确定这是否是一个好的设计,我也不确定是否需要为子类提供类似于
jdbcTemplate
的数据库API对象或与数据库交互的东西

客户
类别

public class Customer {

    private int id;
    private String fullName;
    private boolean active;

    public Customer(int id, String name, boolean active){
        this.id = id;
        this.fullName = name;
        this.active = active;
    }

    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", active=" + active
                + "]";
    }   
}
父数据库访问类:

public class RdbmsManager{

    public RdbmsManager(){
           connectToDatabase();
    }

    private void connectToDatabase(){
           // read from properties files to get DB URL, PORT number etc.
           // Create Datasource object and establish connection to database
           System.out.println("Established Database Connection...");
    }

   // Below method returns the database object children can use to issue commands
    protected DatabaseAPI getDatabaseObject(){
        DatabaseAPI databaseObject = new DatabaseAPI ();
           return databaseObject;
    }

}
CustomerDataManager子类:

public class CustomerDataManager extends RdbmsManager{

    public CustomerDataManager() {
        super(); // call to super will establish database connection from parent class
    }

    public void saveCustomerToDatabase(Customer Customer) {
        getDatabaseAPI().insert(Customer);
    }

    public void deleteCustomerFromDatabase(Customer Customer) {
        getDatabaseAPI().delete(Customer);
    }
}
数据库交互对象的简单实现,重点在于设计:

public class DatabaseAPI{

    protected void insert(Object object){
           System.out.println("inserted the into the database: "+ object.toString());
    }

    protected void delete(Object object){
           System.out.println("Deleted object from database" + object.toString());
    }
}

好的,您非常接近于使用数据库的标准设计之一。
主要区别在于类的名称(例如DAO而不是Manager),并且您正在扩展DB连接池管理器以创建DAO

让我详细说明一下:

  • 数据库应该通过抽象从应用程序中分离出来。为了实现这一点,您通常在数据库的顶部创建一个名为
    的数据抽象层。这有点类似于您的
    RdbmsManager
    类,其要点是抽象掉实际使用的数据库。为了实现这一点,您通常有一个某种类型的数据库访问接口,该接口将由控制数据库所有连接的某个类实现(尽量避免包含“Manager”的名称,因为它实际上无助于澄清这些类的功能)。如果以后您决定更改正在使用的数据库,那么您所需要做的就是为支持新数据库的接口创建一个新的实现,您就完成了

  • 对数据库中实际数据的访问也应该由另一层抽象,通常称为
    数据访问层
    。该层包含的接口封装了对特定类型数据的所有访问(通常为每个表),并允许对其执行
    CRUD
    操作。这些接口通常被命名为
    SomethingDAO
    ,其中“Something”代表被访问对象的类型(“DAO”部分代表“数据访问对象”)。同样,这些接口的实现应该是特定于数据库的,并且当您用另一个数据库替换您使用的数据库时,应该进行更改

  • 数据应使用其他方法传输到客户机代码(通常是业务/应用层),通常是
    DTO
    s(代表“数据传输对象”)。这些(同样)接口公开了DB中表示的对象所需的一些功能,这些功能应该由DB特定(或泛型,视情况而定)类实现

  • 简而言之,这就是理论。网上有很多数据来源(更不用说书籍),可以让你阅读更多关于它的信息

    另一方面,这只是实现DB连接的一种方法。还有很多其他模式,因为有很多设计模式通常涉及企业应用程序,特别是层间通信。让我来介绍一下我认为这些设计模式的最佳来源:

    编辑1: 下面是一个非常简单的代码示例(当然未经测试-视为伪代码):

    公共接口客户{…}
    实现Iterable{…}的公共接口CustomerData
    公共类customerdtosqimpl{
    公共CustomerDTOSQLImpl(ResultSet ResultSet){…}
    @凌驾
    公共迭代器迭代器(){…}
    ...
    }
    公共接口客户道{
    公共CustomerDTO findById(int-id);
    ...
    }
    公共类CustomerDAOSQLImpl{
    @注入
    专用连接;
    @凌驾
    public CustomerDTO findById(int-id){
    PreparedStatement=connection.prepareStatement(“从ID=?”的客户中选择*”;
    语句.setInt(1,id);
    返回新的CustomerDTOSQLImpl(statement.executeQuery());
    }
    ...
    }
    
    为什么要求关闭此问题?谢谢。基本上,我想要的是确保CustomerDataManager或CustomerDAO(如您的建议)在数据库更改时不必更改。这个设计会达到那个抽象级别吗?“CustomerDAO”不会改变,但是您必须为每个支持的DB类型添加一个新的“CustomerDAOImpl”类。我不认为有任何方法可以创建一个通用的实现。嗯,如果你能详细说明dao和dao impl。你能给我一个代码示例吗?我真的应该从经理那里扩展吗?我在想也许我应该让DatabaseManger成为一个提供连接对象的唯一实例的单例。。在设计方面,你认为什么更好?完全正确。DB管理器应该是单例的,并提供到DAO的DB连接(最好通过注入)。
    public interface Customer { ... }
    
    public interface CustomerDTO implements Iterable<Customer> { ... }
    
    public class CustomerDTOSQLImpl {
        public CustomerDTOSQLImpl(ResultSet resultSet) { ... }
    
        @Override
        public Iterator<Customer> iterator() { ... }
    
        ...
    }
    
    public interface CustomerDAO {
        public CustomerDTO findById(int id);
    
        ...
    }
    
    
    public class CustomerDAOSQLImpl {
        @Inject
        private Connection connection;
    
        @Override
        public CustomerDTO findById(int id) {
            PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMER WHERE ID = ?");
            statement.setInt(1, id);
            return new CustomerDTOSQLImpl(statement.executeQuery());
        }
    
        ...
    }