Mybatis反射实现装载Mapper

Mapper类

package cn.lsh.kafka.db.dao;

import cn.lsh.kafka.db.entity.OffsetEntity;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * kafka偏移量(Offset)表数据库访问层
 *
 * @author makejava
 * @since 2020-12-08 14:33:12
 */
public interface OffsetMapper {

	/**
	 * 通过ID查询单条数据
	 *
	 * @param id 主键
	 * @return 实例对象
	 */
	@Select("SELECT * from offset where id = #{id}")
	OffsetEntity queryById(Integer id);

	@Select("SELECT * from offset where group_id = #{groupId} and topic = #{topic} and partition_id = #{partitionId}")
	OffsetEntity queryByCond(@Param("groupId") String groupId, @Param("topic") String topic, @Param("partitionId") int partitionId);

	/**
	 * 查询指定行数据
	 *
	 * @param offset 查询起始位置
	 * @param limit  查询条数
	 * @return 对象列表
	 */
	@Select("SELECT * from offset limit #{limit} offset #{offset}")
	List<OffsetEntity> queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit);

	/**
	 * 通过实体作为筛选条件查询
	 *
	 * @param offset 实例对象
	 * @return 对象列表
	 */
	List<OffsetEntity> queryAll(OffsetEntity offset);

	/**
	 * 新增数据
	 *
	 * @param offset 实例对象
	 * @return 影响行数
	 */
	@Insert("INSERT INTO offset(group_id,topic,partition_id,value,create_date,update_date) VALUES(#{groupId},#{topic},#{partitionId},#{value},#{createDate},#{updateDate})")
	int insert(OffsetEntity offset);

	/**
	 * 修改数据
	 *
	 * @param offset 实例对象
	 * @return 影响行数
	 */
	@Update("UPDATE offset SET value = #{value}, update_date=#{updateDate} where id = #{id}")
	int update(OffsetEntity offset);

	/**
	 * 通过主键删除数据
	 *
	 * @param id 主键
	 * @return 影响行数
	 */
	@Delete("DELETE FROM offset where id = #{id}")
	int deleteById(Integer id);

}

mybatis的Mapper类支持注解的方式映射sql语句,省去了mapper的xml映射文件。

基类Service

package cn.lsh.kafka.db.service;

import org.apache.ibatis.session.SqlSession;

public abstract class BaseService<T> {

	protected SqlSession sqlSession;
	/** 泛型T为实体的Mapper类 */
	protected T mapper;

	public BaseService(SqlSession sqlSession) {
		//为service装载sqlSession
		this.sqlSession = sqlSession;
	}

	protected void commit() {
		this.sqlSession.commit();
	}

	protected void close() {
		//private不能被子类继承,protect可以被子类继承,但是不能被反射出来
		this.close();
	}

	public void setMapper(Class<T> t) {
		try {
			this.mapper = this.sqlSession.getMapper(t);
		} catch (Exception e) {
			this.sqlSession.getConfiguration().addMapper(t);
			this.mapper = sqlSession.getMapper(t);
		}
	}
}

所有Service都继承这个抽象类,这个类主要关注以下三个地方:

  1. 泛型:泛型必须申明为实体对应Mapper映射类;
  2. sqlSession:该类维持一个sqlSession,通过构造器加载,供其继承类使用;
  3. setMapper:实现了一个setMapper方法,该方法自动为service注册Mapper到sqlSession。

业务Service接口

public interface OffsetService {


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    OffsetEntity queryById(Integer id);

    OffsetEntity queryByCond(String groupId, String topic, int partitionId);

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit 查询条数
     * @return 对象列表
     */
    List<OffsetEntity> queryAllByLimit(int offset, int limit);

    /**
     * 新增数据
     *
     * @param offset 实例对象
     * @return 实例对象
     */
    OffsetEntity insert(OffsetEntity offset);

    /**
     * 修改数据
     *
     * @param offset 实例对象
     * @return 实例对象
     */
    OffsetEntity update(OffsetEntity offset);

    void update(int id, long value);

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    boolean deleteById(Integer id);

}

定义业务处理接口方法,没有其他特殊逻辑。

业务接口实现类

public class OffsetServiceImpl extends BaseService<OffsetMapper> implements OffsetService {

    // private OffsetMapper offsetMapper;

    public OffsetServiceImpl(SqlSession sqlSession) {
        super(sqlSession);
    }

    /*public OffsetServiceImpl() {
        TransactionFactory factory = new JdbcTransactionFactory();
        DataSource dataSource = new PooledDataSource("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/bigdata", "root", "admin");
        Environment environment = new Environment("ID", factory, dataSource);
        Configuration conf = new Configuration(environment);
        conf.addMapper(OffsetMapper.class);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(conf);
        this.sqlSession = sessionFactory.openSession();
        offsetMapper = sqlSession.getMapper(OffsetMapper.class);
    }*/

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public OffsetEntity queryById(Integer id) {
        return this.mapper.queryById(id);
    }

    @Override
    public OffsetEntity queryByCond(String groupId, String topic, int partitionId) {
        return this.mapper.queryByCond(groupId, topic, partitionId);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit 查询条数
     * @return 对象列表
     */
    @Override
    public List<OffsetEntity> queryAllByLimit(int offset, int limit) {
        return this.mapper.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param offset 实例对象
     * @return 实例对象
     */
    @Override
    public OffsetEntity insert(OffsetEntity offset) {
        this.mapper.insert(offset);
        return offset;
    }

    /**
     * 修改数据
     *
     * @param offset 实例对象
     * @return 实例对象
     */
    @Override
    public OffsetEntity update(OffsetEntity offset) {
        this.mapper.update(offset);
        return this.queryById(offset.getId());
    }

    @Override
    public void update(int id, long value) {
        OffsetEntity offset = new OffsetEntity();
        offset.setId(id);
        offset.setValue(value);
        offset.setUpdateDate(new Date());
        this.mapper.update(offset);
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        boolean flag = this.mapper.deleteById(id) > 0;
        return flag;
    }

    public static void main(String[] args) {
        // OffsetService service = new OffsetServiceImpl();
        OffsetService service = ServiceFactory.buildService(OffsetService.class);
        OffsetEntity entity = new OffsetEntity();
        entity.setGroupId("11111");
        entity.setPartitionId(1);
        entity.setTopic("adad");
        entity.setValue(10L);
        Date now = new Date();
        entity.setCreateDate(now);
        entity.setUpdateDate(now);
        service.insert(entity);
        OffsetEntity offsetEntity = service.queryById(5);
        System.out.println(offsetEntity);
        ServiceFactory.commitAndClose();
    }
}

需要继承BaseService,并继承其构造器实现。其他就都是业务接口实现了。

Service工厂类

public class ServiceFactory {

	private static SqlSession sqlSession;

	//私有构造器
	private ServiceFactory() {}

	public static SqlSession createSession() {
		//维持一个单例sqlSession
		if (sqlSession == null) {
			TransactionFactory factory = new JdbcTransactionFactory();
			DataSource dataSource = new PooledDataSource("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/bigdata", "root", "admin");
			Environment environment = new Environment("ID", factory, dataSource);
			Configuration conf = new Configuration(environment);
			SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(conf);
			sqlSession = sessionFactory.openSession();
		}
		return sqlSession;
	}

	public static void commit() {
		if (sqlSession != null) {
			sqlSession.commit();
		}
	}

	public static void close() {
		if (sqlSession != null) {
			sqlSession.close();
		}
	}

	public static void commitAndClose() {
		commit();
		close();
	}

	public static <T> T buildService(Class<T> clazz) {
		try {
			String name = clazz.getName();
			String implName = name.replaceAll(clazz.getSimpleName(), "impl.") + clazz.getSimpleName() + "Impl";
			//反射加载service的实现类
			Class<?> implClass = clazz.getClassLoader().loadClass(implName);
			Constructor<?> constructor = implClass.getConstructor(SqlSession.class);
			Object o = constructor.newInstance(createSession());
			String mapperName = name.replaceAll(clazz.getSimpleName(), clazz.getSimpleName().replaceAll("Service", "Mapper")).replaceAll("service", "dao");
			//反射加载Mapper类
			Class<?> mapperClass = clazz.getClassLoader().loadClass(mapperName);
			//反射调用BaseService的setMapper向SQLSession中注册Mapper
			Method setMapper = implClass.getMethod("setMapper", Class.class);
			setMapper.invoke(o, mapperClass);
			return (T) o;
		} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
			throw new RuntimeException("反射Service异常--" + e);
		}
	}
}

通过ServiceFactory反射Service实现类实例。该工厂类采用单例模式,私有化构造器,维护一个SQLSession。主要有两个方法:

  • createSession:这个方法连接数据库,构建sqlSession会话对象;
  • buildService:这个方法通过反射构建Service实现类,主要有以下几步
    1、接收一个Service的class对象
    2、通过class拼装器实现类的全路径名
    3、反射获得service的实现类对象,同时会为其装载SQLSession
    4、反射加载Mapper类
    5、反射调用BaseService的setMapper向SQLSession中注册
    Mapper
    6、返回加载好的Service实现类对象

存在问题

service实现类需要继承BaseService,导致无法继承其他类,还需后续研究改进。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值