实现后台高级查询(中级版)

初级版本的高级查询实现是没有问题的。然而,存在着一些你不尽人意的地方

问题1:拼接SQL依然麻烦,不爽!

问题2:使用了where1=1,降低性能

问题3:从责任分离上考虑,DAO是不应该做SQL拼接的,DAO是负责做CRUD的因为查询对象拥有查询信息,应该把拼接SQL的重任交给他。

1 解决责任分离的问题:

把查询SQL和参数封装到Query对象

public class ProductQueryObject {
    /**
     * 拼接SQL
     * @return 拼接好查询条件的SQL
     * 
     * 此时ProducctQueryObject:
     * 既封装有查询的SQL:querySql属性
     * 也封装了查询的条件:productName,minSalePrice,maxSalePrice属性
     * --------------------------------
     * 可以把ProductQueryObject作为参数,传递给MyBatis.
     */ 
    public String getQuerySql() {
        //拼接SQL
        StringBuilder sql = new StringBuilder(" WHERE 1=1 ");

        //若输入了商品名称
        if (StringUtil.hasLength(productName)) {//名字占位符
            sql.append(" AND productName LIKE CONCAT('%',#{productName},'%')");
        }
        //最低零售价
        if (minSalePrice != null) {
            sql.append(" AND salePrice >= #{minSalePrice}");
        }
        //最高零售价
        if (maxSalePrice != null) {
            sql.append(" AND salePrice <= #{maxSalePrice}");
        }
        System.out.println("sql="+sql);
        return sql.toString();
    }
    private String productName;//商品名称
    private BigDecimal minSalePrice;//最低商品零售价
    private BigDecimal maxSalePrice;//最高商品零售价
    public String getProductName() {
        return productName;
    }
    public BigDecimal getMinSalePrice() {
        return minSalePrice;
    }
    public BigDecimal getMaxSalePrice() {
        return maxSalePrice;
    }
    public void setProductName(String productName) {
        this.productName = productName;
    }
    public void setMinSalePrice(BigDecimal minSalePrice) {
        this.minSalePrice = minSalePrice;
    }
    public void setMaxSalePrice(BigDecimal maxSalePrice) {
        this.maxSalePrice = maxSalePrice;
    }
}

XML映射文件

其中${querySql}是ProductQueryObject对象中的get方法

这里表示:获取ProductQueryObject的querySql属性值,并设置到SQL中:

此时SQL: SELECT * FROM product WHERE 1=1 …….#{productName}…..#{minSale}…..



 
<mapper namespace="cn.itsource.shopping.mapper.ProductMapper">

    
    <select id="list" resultType="Product">
        SELECT * FROM product
    select>

    
    <select id="advanceQuery" parameterType="cn.itsource.shopping.query.ProductQueryObject" resultType="Product">
        SELECT * FROM product ${querySql}
    select>
mapper>

2 解决 WHERE1=1 的问题

public class ProductQueryObject {

    //封装查询条件如:productName = LIKE XX 
    private List conditions = new ArrayList<>();
    //解决  where1=1  的问题
    //拼接查询条件的SQL
    public String getQuerySql() {
        //拼接SQL
        StringBuilder sql = new StringBuilder();

        //若输入了商品名称
        if (StringUtil.hasLength(productName)) {//名字占位符
            conditions.add(" productName LIKE CONCAT('%',#{productName},'%')");
        }
        //最低零售价
        if (minSalePrice != null) {
            conditions.add(" salePrice >= #{minSalePrice}");
        }
        //最高零售价
        if (maxSalePrice != null) {
            conditions.add(" salePrice <= #{maxSalePrice}");
        }
        for (int i = 0; i < conditions.size(); i++) {
            if(i==0){
                sql.append(" WHERE ");
            }else{
                sql.append(" AND ");
            }
            sql.append(conditions.get(i));
        }
        System.out.println("sql="+sql);
        return sql.toString();
    }

    private String productName;//商品名称
    private BigDecimal minSalePrice;//最低商品零售价
    private BigDecimal maxSalePrice;//最高商品零售价
    public String getProductName() {
        return productName;
    }
    public BigDecimal getMinSalePrice() {
        return minSalePrice;
    }
    public BigDecimal getMaxSalePrice() {
        return maxSalePrice;
    }
    public void setProductName(String productName) {
        this.productName = productName;
    }
    public void setMinSalePrice(BigDecimal minSalePrice) {
        this.minSalePrice = minSalePrice;
    }
    public void setMaxSalePrice(BigDecimal maxSalePrice) {
        this.maxSalePrice = maxSalePrice;
    }
}

XML映射文件

跟上面的一样不需要改变!



 
<mapper namespace="cn.itsource.shopping.mapper.ProductMapper">

    
    <select id="list" resultType="Product">
        SELECT * FROM product
    select>

    
    <select id="advanceQuery" parameterType="cn.itsource.shopping.query.ProductQueryObject" resultType="Product">
        SELECT * FROM product ${querySql}
    select>
mapper>

实现类代码

public class ProductDAOImpl implements IProductDAO {

    public List list() {
        SqlSession session = MyBatisUtil.INSTANCE.openSession();
        try {
            return session.selectList("cn.itsource.shopping.mapper.ProductMapper.list");
        } finally {
            session.close();
        }
    }

    public List query(ProductQueryObject qo) {
        SqlSession session = MyBatisUtil.INSTANCE .openSession();   
        try {
            return session.selectList("cn.itsource.shopping.mapper.ProductMapper.advanceQuery", qo);
        } finally {
            session.close();
        }
    }
}

实现接口代码

public interface IProductDAO {
    List list();

    //高级查询的方法
    List query (ProductQueryObject qo);
}

测试类代码

public class ProductDAOTest {

    private IProductDAO dao = new ProductDAOImpl();

    @Test
    public void testList() {
        List list = dao.list();
        for (Product p : list) {
            System.out.println(p);
        }
    }

    @Test
    public void testQuery() {
        ProductQueryObject qo = new ProductQueryObject();
        qo.setProductName("iphone8s");
        qo.setMinSalePrice(new BigDecimal("6000"));
        qo.setMaxSalePrice(new BigDecimal("9000"));
        //------------------------------------
        List list = dao.query(qo);
        for (Product p : list) {
            System.out.println(p);
        }
    }
}

Util工具类

public enum MyBatisUtil {
    INSTANCE;

    private static SqlSessionFactory sessionFactory = null;

    static {
        try {
            sessionFactory = new SqlSessionFactoryBuilder().build(Resources
                    .getResourceAsStream("MyBatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public SqlSession openSession() {
        return sessionFactory.openSession();
    }
}
public class StringUtil {
    public static boolean hasLength(String str) {
        return str != null && !"".equals(str.trim());
    }
}

商品对象类

public class Product {
    private Long id;
    private String productName;
    private String brand;
    private String supplier;
    private BigDecimal salePrice;
    private BigDecimal costPrice;
    private Double cutoff;
    private Long dir_id;//分类编号
    public Long getId() {
        return id;
    }
    public String getProductName() {
        return productName;
    }
    public void setProductName(String productName) {
        this.productName = productName;
    }
    public String getBrand() {
        return brand;
    }
    public String getSupplier() {
        return supplier;
    }
    public BigDecimal getSalePrice() {
        return salePrice;
    }
    public BigDecimal getCostPrice() {
        return costPrice;
    }
    public Double getCutoff() {
        return cutoff;
    }
    public Long getDir_id() {
        return dir_id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public void setSupplier(String supplier) {
        this.supplier = supplier;
    }
    public void setSalePrice(BigDecimal salePrice) {
        this.salePrice = salePrice;
    }
    public void setCostPrice(BigDecimal costPrice) {
        this.costPrice = costPrice;
    }
    public void setCutoff(Double cutoff) {
        this.cutoff = cutoff;
    }
    public void setDir_id(Long dir_id) {
        this.dir_id = dir_id;
    }
    public String toString() {
        return "Product [id=" + id + ", productName=" + productName + ", brand=" + brand + ", suppliet=" + supplier
                + ", salePrice=" + salePrice + ", costPrice=" + costPrice + ", cutoff=" + cutoff + ", dir_id=" + dir_id
                + "]";
    }
}

MyBatis的映射文件

<configuration>
    
    <properties resource="db.properties" />
    
    <typeAliases>
        <typeAlias type="cn.itsource.shopping.domain.Product" alias="Product" />
    typeAliases>
    
    <environments default="development">
        
        <environment id="development">
            
            <transactionManager type="JDBC" />
            
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${usename}" />
                <property name="password" value="${password}" />
            dataSource>
        environment>
    environments>
    
    <mappers>
        <mapper resource="cn\itsource\shopping\domain\ProductMapper.xml" />
    mappers>
configuration>

db.properties文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcdemo?useSSL=false
usename=root
password=111111

日志文件

其中第二行是日志跟踪哪一包具体到哪一个类的错误信息!

log4j.rootLogger=ERROR, stdout

log4j.logger.cn.itsource.shopping=TRACE

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

你可能感兴趣的:(Jdbc)