關於持久層和業務層程式碼封裝的一點點設計
阿新 • • 發佈:2019-02-07
前言:
換公司以前寫了一年半的ERP,持久層框架用的mybatis,基本的一些類和xml是通過mybatis逆向工程自動生成的,所以反射的資料庫有多少表就會生成多少個dao,實際上生成的這些dao裡面的增刪改查方法都是一樣的,不一樣的只是實體型別而已,以前沒什麼經驗只知道這部分程式碼重複也不知道怎麼辦,現在來到這家公司,看了看程式碼,發現這裡已經對持久層的dao和業務層的service進行了封裝,於是自己動手寫了個demo體現一下這種設計,非常好的利用了java的泛型、繼承和多型。
老規矩先上目錄結構:
ps:包名帶_1的是傳統的逆向生成的程式碼,為了掩飾就寫了2個方法。
實體類都是一樣:
public class User {
private Integer id;
private String name;
private String gender;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName (String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
public class Company {
private Integer id;
private String name;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
先看一下_1包裡面的程式碼結構
(結構很清晰,資料庫中每個表都有自己對應的:實體-mapper-service-serviceImpl):
@Component
public interface CompanyMapper {
Company selectByPrimaryKey(Integer id);
}
public interface CompanyService {
Company selectById(Integer id);
}
@Service
public class CompanyServiceImpl implements CompanyService{
@Autowired
private CompanyMapper companyMapper;
@Override
public Company selectById(Integer id) {
return companyMapper.selectByPrimaryKey(id);
}
}
@Component
public interface UserMapper {
User selectByPrimaryKey(Integer id);
}
public interface UserService {
User selectById(Integer id);
}
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public User selectById(Integer id) {
return userMapper.selectByPrimaryKey(id);
}
}
總結:以上是傳統的不帶任何設計的持久層和業務層,缺點非常明顯,沒有充分利用java語言的特點,這樣有多少表就會生成多少重複程式碼,現在看一下帶有設計的程式碼結構:
@Component
public interface BaseMapper<T> {
T selectByPrimaryKey(Integer id);
void updateByPrimaryKey(T t);
}
@Component
public interface CompanyMapper extends BaseMapper<Company>{
}
public interface CompanyService {
}
public abstract class BaseService<D extends BaseMapper<T>,T> {
@Autowired
protected D dao;
public abstract void saveById(Integer id);
}
@Service
public class CompanyServiceImpl extends BaseService<CompanyMapper,Company> implements CompanyService {
@Override
public void saveById(Integer id) {
Company company = this.dao.selectByPrimaryKey(id);
company.setAddress("new address");
this.dao.updateByPrimaryKey(company);
}
}
@Component
public interface UserMapper extends BaseMapper<User>{
}
public interface UserService {
}
@Service
public class UserServiceImpl extends BaseService<UserMapper,User> implements UserService{
@Override
public void saveById(Integer id) {
User user = this.dao.selectByPrimaryKey(id);
user.setGender("F");
this.dao.updateByPrimaryKey(user);
}
}
總結:
1.多出一個泛型實體的BaseMapper來統一管理mybatis提供的增刪改查,保留原來的Mapper去繼承BaseMapper,簡化了重複的增刪改查,每個Mapper只寫與自己相關的方法
2.多出一個泛型Mapper和實體的BaseService來統一管理,這樣寫serviceImpl時繼承BaseService傳入Mapper和實體後,就不用在serviceImpl注入Mapper,由於BaseService是抽象類還能寫一些公共方法讓子類自由實現(體現多型),還能實現自己的service來寫自己的業務邏輯