Java 用于插入和删除域对象的数据库接口API的设计
我正在尝试创建一个好的OOP设计,特别是符合SRP的,用于与数据库接口以插入和删除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基类,基类的职责是建
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特定(或泛型,视情况而定)类实现公共接口客户{…}
实现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());
}
...
}