前言:
换公司以前写了一年半的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来写自己的业务逻辑