Customers can learn about the product information that a merchant has sold through the product details page.

Alter Product Table in the Database

1
2
3
4
5
6
-- Add user_id field into the product table:
ALTER TABLE product ADD user_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0;
UPDATE product SET user_id = 1;
UPDATE user SET type = 2;  -- Change user type to Merchant
SELECT * FROM product;
SELECT * FROM user;

Update Product Model

Copy and paste the following content into Product.java under the common/src/main/java/co.dongchen.shop.common/model directory:

  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
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package co.dongchen.shop.common.model;

import com.google.common.collect.Lists;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

public class Product {

    private Long id;
    private Integer createdAt;
    private Integer updatedAt;
    private String sku;
    private String name;
    private Integer stock;
    private Integer price;
    private Boolean isEnabled;
    private String images;
    private String description;
    private Long userId;

    private String mainImage;
    private List<String> imageList = Lists.newArrayList();
    private Boolean isFavourite;
    private List<MultipartFile> imageFiles;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Integer createdAt) {
        this.createdAt = createdAt;
    }

    public Integer getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Integer updatedAt) {
        this.updatedAt = updatedAt;
    }

    public String getSku() {
        return sku;
    }

    public void setSku(String sku) {
        this.sku = sku;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getStock() {
        return stock;
    }

    public void setStock(Integer stock) {
        this.stock = stock;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    public Boolean getEnabled() {
        return isEnabled;
    }

    public void setEnabled(Boolean enabled) {
        isEnabled = enabled;
    }

    public String getImages() {
        return images;
    }

    public void setImages(String images) {
        this.images = images;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getMainImage() {
        return mainImage;
    }

    public void setMainImage(String mainImage) {
        this.mainImage = mainImage;
    }

    public List<String> getImageList() {
        return imageList;
    }

    public void setImageList(List<String> imageList) {
        this.imageList = imageList;
    }

    public Boolean getFavourite() {
        return isFavourite;
    }

    public void setFavourite(Boolean favourite) {
        isFavourite = favourite;
    }

    public List<MultipartFile> getImageFiles() {
        return imageFiles;
    }

    public void setImageFiles(List<MultipartFile> imageFiles) {
        this.imageFiles = imageFiles;
    }
}

Update produxt.xml

Copy and paste the following content into product.xml under the service/src/main/resources/mapper directory:

 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
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="co.dongchen.shop.mapper.ProductMapper">
    <sql id="productFields">
        p.id, p.created_at, p.updated_at, p.sku, p.name, p.stock, p.price, p.is_enabled, p.images, p.description, p.user_id
    </sql>
    <sql id="whereCondition">
        <where>
            <if test="productCondition.id != null and productCondition.id != 0">
                and p.id = #{productCondition.id}
            </if>
            <if test="productCondition.isEnabled != null and productCondition.isEnabled == true">
                and p.is_enabled = 1
            </if>
            <if test="productCondition.isEnabled != null and productCondition.isEnabled == false">
                and p.is_enabled = 0
            </if>
            <if test="productCondition.name != null and productCondition.name != ''">
                <bind name="likeName" value="'%' + productCondition.name + '%'"/>
                and p.name like #{likeName}
            </if>
        </where>
    </sql>
    <select id="queryPagedProducts" resultType="product">
        select <include refid="productFields"/>
        from product p
        <include refid="whereCondition"/>
        <if test="pageHelperCondition.offSet != null and pageHelperCondition.limit != null">
            limit #{pageHelperCondition.offSet},#{pageHelperCondition.limit}
        </if>
        <if test="pageHelperCondition.offSet == null and pageHelperCondition.limit != null">
            limit #{pageHelperCondition.limit}
        </if>
    </select>
    <select id="queryPagedCount" resultType="long">
        select count(id)
        from product p
        <include refid="whereCondition"/>
    </select>
</mapper>

Create Merchant Mapper

MerchantMapper interface

  • Right click service/src/main/java/co.dongchen.shop/mapper directory: New > Java Class
  • Fill in “MerchantMapper”
  • Change Kind to: Interface
  • Click “OK” button
img

Copy and paste the following content into MerchantMapper.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package co.dongchen.shop.mapper;

import co.dongchen.shop.common.model.User;
import co.dongchen.shop.common.util.PageHelper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface MerchantMapper {

    List<User> queryPagedMerchants(@Param("merchant") User merchant, @Param("pageHelperCondition") PageHelper pageHelperCondition);

}

Create merchant.xml

  • Right click service/src/main/resources/mapper directory: New > File
  • Fill in “merchant.xml”
  • Click “OK” button
img

Copy and paste the following content into merchant.xml:

 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
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="co.dongchen.shop.mapper.MerchantMapper">
    <sql id="merchantFields">
        first_name, last_name, phone, email, type
    </sql>
    <select id="queryPagedMerchants" resultType="merchant">
        select * from user
        <where>
            is_enabled = 1 and type = 2
            <if test="merchant.id != null and merchant.id != 0">
                and id = #{merchant.id}
            </if>
            <if test="merchant.email != null and merchant.email != ''">
                and email = #{merchant.email}
            </if>
        </where>
        order by id desc
        <if test="pageHelperCondition.offSet != null and pageHelperCondition.limit != null">
            limit #{pageHelperCondition.offSet},#{pageHelperCondition.limit}
        </if>
        <if test="pageHelperCondition.offSet == null and pageHelperCondition.limit != null">
            limit #{pageHelperCondition.limit}
        </if>
    </select>
</mapper>

Update mybatis-config.xml

Copy and paste the following content into mybatis-config.xml file under the service/src/main/resources/mybatis directory:

 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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- Disable Caches  -->
        <setting name="cacheEnabled" value="false"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="useGeneratedKeys" value="true"/>
        <setting name="defaultExecutorType" value="REUSE"/>
        <!-- Transaction Timeout -->
        <setting name="defaultStatementTimeout" value="600"/>
    </settings>

    <typeAliases>
        <typeAlias type="co.dongchen.shop.common.model.Product" alias="product" />
        <typeAlias type="co.dongchen.shop.common.model.User" alias="user" />
        <typeAlias type="co.dongchen.shop.common.model.User" alias="merchant" />

    </typeAliases>

    <mappers>
        <mapper resource="mapper/product.xml" />
        <mapper resource="mapper/user.xml" />
        <mapper resource="mapper/merchant.xml" />
    </mappers>

</configuration>

Create MerchantService

  • Right click service/src/main/java/co.dongchen.shop/service directory: New > Java Class
  • Fill in “MerchantService”
  • Click “OK” button
img

Copy and paste the following content into MerchantService.java:

 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
32
33
34
35
36
37
package co.dongchen.shop.service;

import co.dongchen.shop.common.model.User;
import co.dongchen.shop.common.util.PageHelper;
import co.dongchen.shop.mapper.MerchantMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class MerchantService {

    @Autowired
    private MerchantMapper merchantMapper;

    @Value("${fileserver.img_path}")
    private String imgPath;

    public User getMerchantById(Long merchantId) {
        User merchant = new User();
        merchant.setId(merchantId);
        merchant.setType(2);
        List<User> merchants = merchantMapper.queryPagedMerchants(merchant, PageHelper.init(1, 1));
        getImg(merchants);
        if (! merchants.isEmpty()) {
            return merchants.get(0);
        }
        return null;
    }

    private void getImg(List<User> merchants) {
        merchants.forEach(m -> m.setAvatar(imgPath + m.getAvatar()));
    }

}

Update ProductService class

Copy and paste the following content into ProductService.java under the service/src/main/java/co.dongchen.shop/service directory:

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package co.dongchen.shop.service;

import co.dongchen.shop.common.model.Product;
import co.dongchen.shop.common.util.PageHelper;
import co.dongchen.shop.common.util.pager.PagingData;
import co.dongchen.shop.mapper.ProductMapper;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class ProductService {

    @Value("${fileserver.img_path}")
    private String imgPath;

    @Autowired
    private ProductMapper productMapper;

    public PagingData<Product> getProducts(Product productCondition, PageHelper pageHelper) {
        List<Product> products = Lists.newArrayList();
        products = queryWithImgs(productCondition, pageHelper);
        Long count = productMapper.queryPagedCount(productCondition);
        return PagingData.initPaging(products, count, pageHelper.getPageSize(), pageHelper.getPageNumber());
    }

    private List<Product> queryWithImgs(Product productCondition, PageHelper pageHelper) {
        List<Product> products = productMapper.queryPagedProducts(productCondition, pageHelper);
        products.forEach(p -> {
            p.setMainImage(imgPath + p.getMainImage());
            p.setImageList(p.getImageList().stream().map(img -> imgPath + img).collect(Collectors.toList()));
        });
        return products;
    }

    public Product getProductById(Long id) {
        Product productCondition = new Product();
        productCondition.setId(id);
        List<Product> products = queryWithImgs(productCondition, PageHelper.init(1, 1));
        if (! products.isEmpty()) {
            return products.get(0);
        }
        return null;
    }
}

Update ProductController class

Copy and paste the following content into ProductController.java under the controller/src/main/java/co.dongchen.shop/controller directory:

 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
32
33
34
35
36
37
38
39
package co.dongchen.shop.controller;

import co.dongchen.shop.common.model.Product;
import co.dongchen.shop.common.util.PageHelper;
import co.dongchen.shop.common.util.pager.PagingData;
import co.dongchen.shop.service.MerchantService;
import co.dongchen.shop.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ProductController {

    @Autowired
    private ProductService productService;

    @Autowired
    private MerchantService merchantService;

    @RequestMapping("/product/pagination")
    public String pagination(PageHelper pageHelper, Product productCondition, ModelMap modelMap) {
        PagingData<Product> pageData = productService.getProducts(productCondition, PageHelper.init(pageHelper.getPageSize(), pageHelper.getPageNumber()));
        modelMap.put("pageData", pageData);
        modelMap.put("productCondition", productCondition);
        return "/product/pagination";
    }

    @RequestMapping("product/info")
    public String productInfo(Long id, ModelMap modelMap) {
        Product product = productService.getProductById(id);
        if (product.getUserId() != null && ! product.getUserId().equals(0L)) {
            modelMap.put("merchant", merchantService.getMerchantById(product.getUserId()));
        }
        modelMap.put("product", product);
        return "/product/info";
    }
}

Create product/info.ftl in Controller Module

  • Right click controller/src/main/resources/templates/product directory: New > File
  • Fill in “info.ftl”
  • Click “OK” button
img

Copy and paste the following content into info.ftl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<html lang="en-NZ">
<@common.header/>
<body>
    ${errorMsg!}
    ${successMsg!}

    <h1>Product Info</h1>
    <p>Product: ${(product.name)!}</p>
    <h1>Merchant Info</h1>
    <p>Merchant: ${(merchant.firstName)!} ${(merchant.lastName)!}</p>

</body>
<@common.footer/>
</html>

Verify

Run the App

1
2
// Short Cut for "Run the Program"
Alt + Shift + F10
img

Choose the correspondent option and press enter.

View Product Info Page in the Browser

1
http://localhost:8080/product/info?id=1
img

Buy me a coffeeBuy me a coffee