I'm attempting to refactor and normalize a table of products in MySQL like the one below:
CREATE TABLE `products` (
`id` varchar(45) NOT NULL, # alphanumeric product codes
`productCategory` varchar(45) NOT NULL,
`productSubCategory` varchar(45) DEFAULT NULL,
`productRange` varchar(45) NOT NULL,
`productClass` varchar(45) DEFAULT NULL,
`name` text NOT NULL,
`size` int(11) NOT NULL,
`sizeMeasure` varchar(5) NOT NULL,
`boxQuantity` int(11) NOT NULL,
`sellingPrice` double NOT NULL,
`rrp` double DEFAULT NULL,
`ordinalValue` int(11) NOT NULL,
PRIMARY KEY (`id`)
)
What I believe needs to be refactored are the productCategory
,productSubCategory
, and productRange
fields. The reason for this is that I need to be able to get the hierarchical structure of the categories. It is also planned to add metadata to the categories.
The table fields currently contain data as follows:
productCategory productSubCategory productRange
---------------------------------------------------------
retail retail_solution1 retail_solution1_range1
retail retail_solution2 retail_solution2_range2
retail retail_solution3 retail_solution3_range3
professional prof_solution1 prof_solution1_range1
professional prof_solution1 prof_solution1_range2
professional prof_solution1 prof_solution1_range3
professional prof_solution2 prof_solution2_range1
professional prof_solution2 prof_solution2_range2
professional prof_solution2 prof_solution2_range3
... ... ...
Essentially within the productCategory
RETAIL set the productSubCategory
and productRange
fields have the same VARCHAR(45)
values.
The depth of this tree is highly unlikely to change in the future. The most common changes will likely be made to category names.
I've looked at the adjacency list and nested set models and am somehow feeling more inclined to use the nested set model.
What I have so far for the nested set model approach:
Adding a category:
CREATE PROCEDURE `addCategory`(IN parent VARCHAR(45), IN child VARCHAR(45))
BEGIN
SELECT @myLeft := lft FROM product_category
WHERE name = parent LIMIT 1;
UPDATE product_category SET rgt = rgt + 2 WHERE rgt > @myLeft;
UPDATE product_category SET lft = lft + 2 WHERE lft > @myLeft;
INSERT INTO product_category(name, lft, rgt) VALUES(child, @myLeft + 1, @myLeft + 2);
END
Deleting a category:
CREATE PROCEDURE `deleteCategory`(IN name VARCHAR(45))
BEGIN
SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
FROM product_category
WHERE name = name;
DELETE FROM product_category WHERE lft BETWEEN @myLeft AND @myRight;
UPDATE product_category SET rgt = rgt - @myWidth WHERE rgt > @myRight;
UPDATE product_category SET lft = lft - @myWidth WHERE lft > @myRight;
END
I would like to have the sql in the java web app rather than stored procedures though. I'm using Spring's JDBCTemplate
for all data access. I'm not really sure at present how to approach this as I haven't used multi-statement queries with JDBCTemplate
before.
Ideally I'd also want to test the data access layer using DBUnit.
What is throwing me off on this project is that somehow I feel more importance needs to be given to the top level categories. Perhaps the top level categories of RETAIL and PROFESSIONAL should be product types rather than categories?
Any guidance would be greatly appreciated. Thanks.