package com.example.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.math.BigDecimal;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableName;
@Data
@TableName("goods")
public class Goods implements Serializable {
@TableId(type = IdType.AUTO)
private Long id;
@TableField(value="name")
private String name;
private String storage;
private String goodsType; // 改为驼峰命名,与数据库goods_type对应
private Long count;
private String remark;
private BigDecimal price;
}
package com.example.model;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.io.Serializable;
@Data
public class Order implements Serializable{
private Long orderId;
private Long userId;
private Date createTime;
private BigDecimal totalAmount;
private List<OrderItem> orderItems; // 关联订单项,创建订单时可一起处理
private String status;
}
package com.example.model;
import lombok.Data;
import java.math.BigDecimal;
import java.io.Serializable;
@Data
public class OrderItem implements Serializable{
private Long itemId;
private Long orderId;
private Long goodsId;
private String goodsName;
private BigDecimal price;
private Integer quantity;
}
package com.example.model;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private Long userId; // 对应表中的 id
private String no; // 对应表中的 no
private String name; // 对应表中的 name
private String password; // 对应表中的 password
private Integer age; // 对应表中的 age(int 类型在 Java 中对应 Integer)
private String sex; // 对应表中的 sex
private String phone; // 对应表中的 phone
private Long roleId; // 对应表中的 role_id(Java 中一般用驼峰命名法)
private Boolean isValid; // 对应表中的 is_valid(tinyint(1) 在 Java 中一般用 Boolean 表示)
public Long getRoleId() {
return roleId;
}
public void setRoleId(Long roleId) {
this.roleId = roleId;
}
}
package com.example.order.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
package com.example.order.controller;
import com.example.model.Goods;
import com.example.model.Order;
import com.example.model.OrderItem;
import com.example.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
@RestController
@RequestMapping("/orders")
public class OrderController {
private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
private final Map<Long, Order> orderMap = new HashMap<>();
private final AtomicLong idGenerator = new AtomicLong(1);
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
// @PostMapping("/create")
// public Order createOrder(OrderRequest request) {
// try {
// // 调用用户服务获取用户信息
// User user = getUser(request.getUserId());
// if (user == null) {
// logger.error("未找到用户信息,用户 ID: {}", request.getUserId());
// return null;
// }
//
// List<OrderItem> orderItems = new ArrayList<>();
// BigDecimal totalAmount = BigDecimal.ZERO;
//
// for (OrderItemRequest itemRequest : request.getOrderItems()) {
// Goods goods = getGoods(itemRequest.getGoodsId());
// if (goods != null) {
// OrderItem orderItem = new OrderItem();
// orderItem.setGoodsId(goods.getId());
// orderItem.setGoodsName(goods.getName());
// orderItem.setPrice(goods.getPrice());
// orderItem.setQuantity(itemRequest.getQuantity());
// orderItems.add(orderItem);
// totalAmount = totalAmount.add(goods.getPrice().multiply(BigDecimal.valueOf(itemRequest.getQuantity())));
// } else {
// logger.warn("未找到商品信息,商品 ID: {}", itemRequest.getGoodsId());
// }
// }
//
// // 创建订单
// Order order = new Order();
// order.setOrderId(idGenerator.getAndIncrement());
// order.setUserId(request.getUserId());
// order.setCreateTime(new Date());
// order.setTotalAmount(totalAmount);
// order.setOrderItems(orderItems);
// order.setStatus("CREATED");
//
// orderMap.put(order.getOrderId(), order);
// return order;
// } catch (Exception e) {
// logger.error("创建订单时发生异常", e);
// return null;
// }
// }
//
// private User getUser(Long userId) {
// try {
// ServiceInstance instance = loadBalancerClient.choose("user-service");
// if (instance == null) {
// logger.error("未找到 user - service 的实例");
// return null;
// }
// String url = String.format("http://%s:%d/users/%d", instance.getHost(), instance.getPort(), userId);
// return restTemplate.getForObject(url, User.class);
// } catch (Exception e) {
// logger.error("调用用户服务获取用户信息时发生异常,用户 ID: {}", userId, e);
// return null;
// }
// }
//
// private Goods getGoods(Long goodsId) {
// try {
// ServiceInstance instance = loadBalancerClient.choose("goods-service");
// String url = String.format("http://%s:%d/goods/%d", instance.getHost(), instance.getPort(), goodsId);
// return restTemplate.getForObject(url, Goods.class);
// } catch (Exception e) {
// logger.error("调用商品服务获取商品信息时发生异常,商品 ID: {}", goodsId, e);
// return null;
// }
// }
@PostMapping(value = "/create", consumes = { "application/x-www-form-urlencoded", "application/json" })
public Order createOrder(
@RequestParam("userId") Long userId,
@RequestParam("goodsId") List<Long> goodsIds,
@RequestParam("quantity") List<Integer> quantities) {
try {
// 检查参数有效性
if (userId == null || goodsIds == null || quantities == null || goodsIds.size() != quantities.size()) {
logger.error("创建订单失败:参数不完整或无效");
return null;
}
// 调用用户服务获取用户信息
User user = getUser(userId);
if (user == null) {
logger.error("未找到用户信息,用户 ID: {}", userId);
return null;
}
// 构建订单项
List<OrderItem> orderItems = new ArrayList<>();
BigDecimal totalAmount = BigDecimal.ZERO;
for (int i = 0; i < goodsIds.size(); i++) {
Long goodsId = goodsIds.get(i);
Integer quantity = quantities.get(i);
Goods goods = getGoods(goodsId);
if (goods != null) {
OrderItem orderItem = new OrderItem();
orderItem.setGoodsId(goods.getId());
orderItem.setGoodsName(goods.getName());
orderItem.setPrice(goods.getPrice());
orderItem.setQuantity(quantity);
orderItems.add(orderItem);
totalAmount = totalAmount.add(goods.getPrice().multiply(BigDecimal.valueOf(quantity)));
} else {
logger.warn("未找到商品信息,商品 ID: {}", goodsId);
}
}
// 创建订单
Order order = new Order();
order.setOrderId(idGenerator.getAndIncrement());
order.setUserId(userId);
order.setCreateTime(new Date());
order.setTotalAmount(totalAmount);
order.setOrderItems(orderItems);
order.setStatus("CREATED");
orderMap.put(order.getOrderId(), order);
return order;
} catch (Exception e) {
logger.error("创建订单时发生异常", e);
return null;
}
}
private User getUser(Long userId) {
try {
ServiceInstance instance = loadBalancerClient.choose("service-user");
if (instance == null) {
logger.error("service-user的实例");
return null;
}
String url = String.format("http://%s:%d/users/%d", instance.getHost(), instance.getPort(), userId);
return restTemplate.getForObject(url, User.class);
} catch (Exception e) {
logger.error("调用用户服务获取用户信息时发生异常,用户 ID: {}", userId, e);
return null;
}
}
private Goods getGoods(Long goodsId) {
try {
ServiceInstance instance = loadBalancerClient.choose("service-goods");
String url = String.format("http://%s:%d/goods/%d", instance.getHost(), instance.getPort(), goodsId);
return restTemplate.getForObject(url, Goods.class);
} catch (Exception e) {
logger.error("调用商品服务获取商品信息时发生异常,商品 ID: {}", goodsId, e);
return null;
}
}
@GetMapping("/{orderId}")
public Order getOrder(@PathVariable Long orderId) {
return orderMap.getOrDefault(orderId, null);
}
// 公开内部请求类(用于 x - www - form - urlencoded)
public static class OrderRequest {
private Long userId;
private List<OrderItemRequest> orderItems;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public List<OrderItemRequest> getOrderItems() {
return orderItems;
}
public void setOrderItems(List<OrderItemRequest> orderItems) {
this.orderItems = orderItems;
}
}
public static class OrderItemRequest {
private Long goodsId;
private Integer quantity;
public Long getGoodsId() {
return goodsId;
}
public void setGoodsId(Long goodsId) {
this.goodsId = goodsId;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
}
}
//package com.example.order.mapper;
//
//import com.example.model.Order;
//import com.example.model.OrderItem;
//import org.apache.ibatis.annotations.Mapper;
//import org.apache.ibatis.annotations.Insert;
//import org.apache.ibatis.annotations.Options;
//
//@Mapper
//public interface OrderMapper<OrderItem, Order> {
//
// // 插入订单主表数据,同时获取自增的 order_id
// @Insert("INSERT INTO `order` (user_id, create_time, total_amount, status) " +
// "VALUES (#{userId}, #{createTime}, #{totalAmount}, #{status})")
// @Options(useGeneratedKeys = true, keyProperty = "orderId", keyColumn = "order_id")
// void insertOrder(Order order);
//
// // 插入订单项数据
// @Insert("INSERT INTO order_item (order_id, goods_id, goods_name, price, quantity) " +
// "VALUES (#{orderId}, #{goodsId}, #{goodsName}, #{price}, #{quantity})")
// void insertOrderItem(OrderItem orderItem);
//}
package com.example.order.mapper;
import com.example.model.Order;
import com.example.model.OrderItem;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
@Mapper // 必须添加该注解,让 MyBatis 扫描并创建 Mapper Bean
public interface OrderMapper {
@Insert("INSERT INTO `order` (user_id, create_time, total_amount, status) " +
"VALUES (#{userId}, #{createTime}, #{totalAmount}, #{status})")
@Options(useGeneratedKeys = true, keyProperty = "orderId", keyColumn = "order_id")
void insertOrder(Order order);
@Insert("INSERT INTO order_item (order_id, goods_id, goods_name, price, quantity) " +
"VALUES (#{orderId}, #{goodsId}, #{goodsName}, #{price}, #{quantity})")
void insertOrderItem(OrderItem orderItem);
}
package com.example.order.service;
import com.example.order.mapper.OrderMapper;
import com.example.model.Order;
import com.example.model.OrderItem;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
@Service
public class OrderService {
private final OrderMapper orderMapper;
public OrderService(OrderMapper orderMapper) {
this.orderMapper = orderMapper;
}
@Transactional
public Order createOrder(Order order) {
// 设置订单创建时间
order.setCreateTime(new Date());
// 先插入订单主表,获取自增的 orderId
orderMapper.insertOrder(order);
Long orderId = order.getOrderId();
// 遍历订单项,设置 orderId 后插入
List<OrderItem> orderItems = order.getOrderItems();
if (orderItems != null && !orderItems.isEmpty()) {
for (OrderItem item : orderItems) {
item.setOrderId(orderId);
orderMapper.insertOrderItem(item);
}
}
return order;
}
}
package com.example.order;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.example.order.mapper")
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
<?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="com.example.mapper.OrderMapper">
<resultMap id="OrderResultMap" type="com.example.model.Order">
<id column="order_id" property="orderId"/>
<result column="order_user_id" property="orderUserId"/>
<result column="order_create_time" property="orderCreateTime"/>
<result column="order_total_amount" property="orderTotalAmount"/>
<result column="order_status" property="orderStatus"/>
</resultMap>
<select id="selectOrderById" parameterType="java.lang.Long" resultMap="OrderResultMap">
SELECT order_id, user_id, create_time, total_amount, status
FROM `order`
WHERE order_id = #{orderId}
</select>
<insert id="insertOrder" parameterType="com.example.model.Order" useGeneratedKeys="true" keyProperty="orderId">
INSERT INTO `order` (user_id, create_time, total_amount, status)
VALUES (#{orderUserId}, #{orderCreateTime}, #{orderTotalAmount}, #{orderStatus})
</insert>
<update id="updateOrder" parameterType="com.example.model.Order">
UPDATE `order`
SET user_id = #{orderUserId},
create_time = #{orderCreateTime},
total_amount = #{orderTotalAmount},
status = #{orderStatus}
WHERE order_id = #{orderId}
</update>
<delete id="deleteOrder" parameterType="java.lang.Long">
DELETE FROM `order`
WHERE order_id = #{orderId}
</delete>
</mapper>
server:
port: 8000
spring:
main:
allow-bean-definition-overriding: true
datasource:
url: jdbc:mysql://localhost:3306/hdms?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
application:
name: service-order
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
jackson: # 添加Jackson配置确保BigDecimal序列化正常
default-property-inclusion: non_null
serialization:
write-dates-as-timestamps: false
deserialization:
fail-on-unknown-properties: false
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 开启驼峰命名
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 启用SQL日志
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.example.model
mapper-scan: com.example.order.mapper
package com.example.user.controller;
import com.example.model.User;
import com.example.user.service.UserService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getById(id); // 调用 UserService 的查询方法
}
@PostMapping("/create")
public User save(User user) {
return userService.save(user);
}
}
package com.example.user.mapper;
import com.example.model.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper<User> {
// 添加selectById方法声明
User selectById(Long id);
// 保持原有方法
User selectUserById(Long id);
// 新增基础CRUD方法
List<User> selectAll();
int insertUser(User user);
int updateUser(User user);
int deleteUser(Long id);
}
package com.example.user.service;
import com.example.model.Goods;
import com.example.user.mapper.UserMapper;
import com.example.model.User;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserMapper userMapper;
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User save(User user) {
// 设置 is_valid 的值
user.setIsValid(true);
// 设置 role_id 的值(假设之前已经处理过 role_id 的问题)
user.setRoleId(1L);
userMapper.insertUser(user);
return user;
}
public User getById(Long id) {
return (User) userMapper.selectById(id); // MyBatis-Plus 内置的根据id查询方法
}
}
package com.example.user;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.example.user.mapper")
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
<?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="com.example.user.mapper.UserMapper">
<!-- 使用正确的实体类路径 -->
<resultMap id="UserResultMap" type="com.example.user.entity.User">
<id column="id" property="id"/>
<result column="no" property="no"/>
<result column="name" property="name"/>
<result column="password" property="password"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<result column="phone" property="phone"/>
<result column="role_id" property="roleId"/>
<result column="is_valid" property="isValid"/>
</resultMap>
<!-- 添加selectById方法 -->
<select id="selectById" resultMap="UserResultMap">
SELECT id, no, name, password, age, sex, phone, role_id, is_valid
FROM user
WHERE id = #{id}
</select>
<!-- 简化参数类型声明 -->
<select id="selectUserById" resultMap="UserResultMap">
SELECT id, no, name, password, age, sex, phone, role_id, is_valid
FROM user
WHERE id = #{id}
</select>
<!-- 添加基础CRUD操作 -->
<select id="selectAll" resultMap="UserResultMap">
SELECT * FROM user
</select>
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (no, name, password, age, sex, phone, role_id, is_valid)
VALUES (#{no}, #{name}, #{password}, #{age}, #{sex}, #{phone}, #{roleId}, #{isValid})
</insert>
<update id="updateUser">
UPDATE user SET
no = #{no},
name = #{name},
password = #{password},
age = #{age},
sex = #{sex},
phone = #{phone},
role_id = #{roleId},
is_valid = #{isValid}
WHERE id = #{id}
</update>
<delete id="deleteUser">
DELETE FROM user WHERE id = #{id}
</delete>
</mapper>
server:
port: 9000
spring:
main:
allow-bean-definition-overriding: true
datasource:
url: jdbc:mysql://localhost:3306/hdms?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
application:
name: service-user
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
jackson: # 添加Jackson配置确保BigDecimal序列化正常
default-property-inclusion: non_null
serialization:
write-dates-as-timestamps: false
deserialization:
fail-on-unknown-properties: false
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 开启驼峰命名
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 启用SQL日志
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.example.model
logging:
level:
com.example.user.mapper: TRACE
出现问题:2025-06-17T15:19:50.565+08:00 ERROR 21148 --- [service-order] [nio-8000-exec-2] c.e.order.controller.OrderController : service-user的实例
2025-06-17T15:19:50.565+08:00 ERROR 21148 --- [service-order] [nio-8000-exec-2] c.e.order.controller.OrderController : 未找到用户信息,用户 ID: 2
最新发布