javaweb----dao重构实现

实体类,与数据库的字段映射。。。。。处理

复制代码
package cn.edu.cque.mall.entity;

import cn.edu.cque.mall.common.Column;
import lombok.Data;
import lombok.ToString;

import java.util.Date;

/**
 * @ClassName Product
 * @Description Product实体类
 * @Author YoungWinter
 * @Date 2020/9/22 14:10
 * @Version 1.0
 **/
@Data
@ToString
public class Product {
    // ID
    @Column("pid")
    private String id;
    // 商品名称A
    @Column("pname")
    private String name;
    // 商品的市场价格
    @Column("market_price")
    private Double marketPrice;
    // 商品的商城价格
    @Column("shop_price")
    private Double shopPrice;
    // 商品的图片URL
    @Column("pimage")
    private String image;
    // 商品上架的时间
    @Column("pdate")
    private Date createDate;
    // 是否热销 1 热销 0 不是热销
    @Column("is_hot")
    private Integer isHot;
    // 商品的描述
    @Column("pdesc")
    private String desc;
    // 是否上架 0 上架 1 下架
    @Column("pflag")
    private Integer flag;
    // 商品的分类ID
    @Column("cid")
    private String cid;
}
复制代码

dao接口的抽象方法的注解sql,,注解对象的定义实现:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Path {
    String value();
}

dao层编写层接口,抽象方法加注解的方式体现。。。。。形成目标接口

SQL注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Sql {
    String value();
}

接口的具体内容:

复制代码
package cn.edu.cque.mall.mapper;

import cn.edu.cque.mall.common.Sql;
import cn.edu.cque.mall.entity.Product;

import java.util.List;

/**
 * @ClassName ProductMapper
 * @Description TODO
 * @Author YoungWinter
 * @Date 2020/9/23 16:33
 * @Version 1.0
 **/
public interface ProductMapper {

    @Sql("select * from product where pid = ?")
    Product findById(String id);

    @Sql("select count(*) from product where cid = ?")
    int findTotalNumber(String cid);

    @Sql("select * from product where cid = ? limit ?, ?")
    List<Product> findListByCidAndPage(String cid, int index, int pageSize);

    @Sql("select * from product where is_hot = ? limit ?, ?")
    List<Product> findHot(int isHot, int index, int size);

    @Sql("select * from product order by pdate desc limit ?, ?")
    List<Product> findNews(int isHot, int index, int size);

    @Sql("select * from product where cid = ?")
    List<Product> findListByCid(String cid);
}
复制代码

然后就利用proxy动态代理技术,对方法增强。。。。。实现业务逻辑,实现  InvocationHandler  接口

复制代码
package cn.edu.cque.mall.common;

import cn.edu.cque.mall.entity.Product;
import cn.edu.cque.mall.utils.DruidUtil;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.lang.reflect.*;
import java.sql.ResultSet;
import java.util.List;

/**
 * @ClassName MapperHandler
 * @Description TODO
 * @Author YoungWinter
 * @Date 2020/9/23 16:12
 * @Version 1.0
 **/
public class MapperHandler implements InvocationHandler {

    private JdbcTemplate template = new JdbcTemplate(DruidUtil.getDataSource());


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 1 获取sql语句
        String sql = method.getAnnotation(Sql.class).value();
        // 2 获取返回值类型用于封装对象
        Class returnType = method.getReturnType();
        boolean isList = false;
        if (returnType.equals(List.class)) {
            // java.util.Map<cn.edu.cque.mall.entity.Category,String>
            isList = true;
            returnType = (Class)(((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0]);
        }
        // 3 使用JdbcTemplate去执行sql并返回结果
        List list = template.query(sql, new ProductRowMapper(returnType), args);
        // 4 根据返回值类型返回结果
        // 4.1 如果是List类型,直接返回
        if (isList)
            return list;
        // 4.2 如果不是List类型,返回list的第一个元素
        if (list != null && list.size() > 0)
            return list.get(0);
        return null;
    }


    // 将数据库中的数据封装成实体类的一个内部类
    private class ProductRowMapper<T> implements RowMapper<T> {

        public ProductRowMapper(Class<T> entityClass) {
            this.entityClass = entityClass;
        }

        // 实体类类型
        private Class<T> entityClass;

        @Override
        public T mapRow(ResultSet rs, int rowNum) {
            T t = null;
            try {
                t = entityClass.newInstance();
                // 封装对象
                // 找到属性的setter,然后将对应的列数据通过setter封装到实体类中
                Field[] fields = entityClass.getDeclaredFields();
                for (Field field : fields) {
                    // name ---> setName()
                    Method method = entityClass.getDeclaredMethod(getSetter(field.getName()), field.getType());
                    method.invoke(t, rs.getObject(field.getAnnotation(Column.class).value()));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return t;
        }
    }

    private String getSetter(String name) {
        String first = String.valueOf(name.charAt(0)).toUpperCase();
        String substring = name.substring(1);
        return "set" + first + substring;
    }
}
复制代码

处理器对象。。业务逻辑就是反射技术获取接口里面的注解与方法还有实体类的相关信息。。。。。然后调用getset方法数据结果集封装

具体看代码了解。。。。。

 

posted on   白嫖老郭  阅读(109)  评论(0编辑  收藏  举报

编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示