1.引入相关依赖:
2.common:
public class SnowFlakeIDGenerator { private static SnowFlake snowFlake = null; private static long workid = 5; private static long datacenterId = 31; static{ snowFlake = new SnowFlake(workid,datacenterId); } public static void main(String[] args) { System.out.println("snoflake:"+generateSnowFlakeId()); } /** * 雪花算法ID生成,全局唯一 * @return * long id */ public final static long generateSnowFlakeId(){ return snowFlake.nextId(); } static class SnowFlake{ // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) private final static long twepoch = 1288834974657L; // 机器标识位数 private final static long workerIdBits = 5L; // 数据中心标识位数 private final static long datacenterIdBits = 5L; // 机器ID最大值 private final static long maxWorkerId = -1L ^ (-1L << workerIdBits); // 数据中心ID最大值 private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 毫秒内自增位 private final static long sequenceBits = 12L; // 机器ID偏左移12位 private final static long workerIdShift = sequenceBits; // 数据中心ID左移17位 private final static long datacenterIdShift = sequenceBits + workerIdBits; // 时间毫秒左移22位 private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; private final static long sequenceMask = -1L ^ (-1L << sequenceBits); /* 上次生产id时间戳 */ private static long lastTimestamp = -1L; // 0,并发控制 private long sequence = 0L; private final long workerId; // 数据标识id部分 private final long datacenterId; public SnowFlake(){ this.datacenterId = getDatacenterId(maxDatacenterId); this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); } /** * @param workerId * 工作机器ID * @param datacenterId * 序列号 */ public SnowFlake(long workerId, long datacenterId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } if (datacenterId > maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); } this.workerId = workerId; this.datacenterId = datacenterId; } /** * 获取下一个ID * * @return */ protected synchronized long nextId() { long timestamp = timeGen(); if (timestamp < lastTimestamp) { throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } if (lastTimestamp == timestamp) { // 当前毫秒内,则+1 sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { // 当前毫秒内计数满了,则等待下一秒 timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = timestamp; // ID偏移组合生成最终的ID,并返回ID long nextId = ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; return nextId; } private long tilNextMillis(final long lastTimestamp) { long timestamp = this.timeGen(); while (timestamp <= lastTimestamp) { timestamp = this.timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } /** * <p> * 获取 maxWorkerId * </p> */ protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { StringBuffer mpid = new StringBuffer(); mpid.append(datacenterId); String name = ManagementFactory.getRuntimeMXBean().getName(); if (!name.isEmpty()) { /* * GET jvmPid */ mpid.append(name.split("@")[0]); } /* * MAC + PID 的 hashcode 获取16个低位 */ return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); } /** * <p> * 数据标识id部分 * </p> */ protected static long getDatacenterId(long maxDatacenterId) { long id = 0L; try { InetAddress ip = InetAddress.getLocalHost(); NetworkInterface network = NetworkInterface.getByInetAddress(ip); if (network == null) { id = 1L; } else { byte[] mac = network.getHardwareAddress(); id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; id = id % (maxDatacenterId + 1); } } catch (Exception e) { System.out.println(" getDatacenterId: " + e.getMessage()); } return id; } } }
2.配置文件的生成:
@Configuration public class CommonConfiguration { //注册到容器中 @Bean public ConfigurationCustomizer configurationCustomizer(){ return new ConfigurationCustomizer(){ @Override public void customize(org.apache.ibatis.session.Configuration configuration) { //开启驼峰命名规则 configuration.setMapUnderscoreToCamelCase(true); } }; } }
3.controller:
@Slf4j @RestController public class ShardingController { @Autowired OrderServiceImpl orderService; @GetMapping("/confirm_order") public String confirmOrder(int sequenceId){ long id = orderService.confirmOrder(sequenceId); return "创建订单成功:订单ID = " + id; } @GetMapping("/order_histroy_list") public OrderInfoDto orderHistoryList(){ return orderService.selectAll(); } /** * 删除历史订单 * @param orderId * @return */ @GetMapping("/delete_histroy_order") public String deleteHistroyOrder(long orderId){ return orderService.deleteData(orderId); } /** * 更改历史订单状态 * @param orderId * @param status * @return */ @GetMapping("/update_histroy_order") public int updateHistoryOrderStatus(long orderId,String status){ return orderService.updateOrder(orderId,status); } /** * range orderid {200000000000000000 - 400000000000000000} * @param start * @param end * @return */ @GetMapping("/order_range_list") public OrderInfoDto orderRangeList(long start,long end){ return orderService.selectOrderRange(start,end); } /** * range userid {1-20} * @param start * @param end * @return */ @GetMapping("/item_range_list") public OrderInfoDto orderItemRangeList(int start,int end){ return orderService.selectOrderItemRange(start,end); } /** * 笛卡尔积测试 * @param start * @param end * @return */ @GetMapping("/item_range_in_list") public OrderInfoDto orderItemRangeInList(long start,long end){ return orderService.selectOrderItemWithIn(start,end); } @GetMapping("/item_page_list") public OrderInfoDto orderPageList(long offset,long size){ return orderService.selectOrderPageList(offset,size); } }
dto 对象:
@AllArgsConstructor @RequiredArgsConstructor @Setter @Getter public class OrderInfoDto { private List<Order> order; private List<OrderItem> item; }
实体对象:
public class Address { private static final long serialVersionUID = 661434701950670670L; private Long addressId; private String addressName; public Long getAddressId() { return addressId; } public void setAddressId(final Long addressId) { this.addressId = addressId; } public String getAddressName() { return addressName; } public void setAddressName(final String addressName) { this.addressName = addressName; } }
Oder对象:
@Mapper public interface OrderItemMapper { @Options(useGeneratedKeys = true,keyProperty = "orderItemId",keyColumn = "order_item_id") @Insert("INSERT INTO t_order_item (order_id, user_id, status) VALUES (#{orderId,jdbcType=INTEGER}," + " #{userId,jdbcType=INTEGER}, #{status,jdbcType=VARCHAR})") long insert(OrderItem order) throws SQLException; @Delete("DELETE FROM t_order_item WHERE order_id = #{orderId}") void delete(long orderId) throws SQLException; /** * 查询所有数据 * @return * @throws SQLException */ @Select("SELECT i.* FROM t_order o, t_order_item i WHERE o.order_id = i.order_id") List<OrderItem> selectAll() throws SQLException; /** * 绑定表,避免无笛卡尔积查询现象, * @param start * @param end * @return * @throws SQLException */ @Select("SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.order_id = 0 or o.order_id = 1") List<OrderItem> selectWithInCondition(@Param("start") long start,@Param("end") long end) throws SQLException; /** * 不支持该路由规则 */ @Select("SELECT i.* FROM t_order o, t_order_item i WHERE o.order_id = i.order_id" + " AND o.user_id BETWEEN #{start} AND #{end}") List<OrderItem> selectRange(@Param("start") int start,@Param("end") int end) throws SQLException; @Update("update t_order_item set status = #{status} where order_id = #{orderId}") int update(@Param("orderId") long orderId,@Param("status") String status) throws SQLException; }
server层:
package com.tl.it.edu.service; import com.tl.it.edu.dto.OrderInfoDto; import com.tl.it.edu.entity.Order; import com.tl.it.edu.entity.OrderItem; import com.tl.it.edu.mapper.OrderItemMapper; import com.tl.it.edu.mapper.OrderMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.sql.SQLException; /** * ,;,,; * ,;;'( 社 * __ ,;;' ' \ 会 * /' '\'~~'~' \ /'\.) 主 * ,;( ) / |. 义 *,;' \ /-.,,( ) \ 码 * ) / ) / )| 农 * || || \) * (_\ (_\ * @author :杨过 * @date :Created in 2019/11/17 17:25 * @version: V1.0 * @slogan: 天下风云出我辈,一入代码岁月催 * @description: **/ @Slf4j @Service public class OrderServiceImpl { @Autowired OrderMapper orderMapper; @Autowired OrderItemMapper orderItemMapper; @Transactional public long confirmOrder(int sequenceId){ //创建订单 Order order = new Order(); order.setAddressId(sequenceId); order.setUserId(sequenceId); order.setStatus("创建订单"); try { orderMapper.insert(order); //订单对应产品 OrderItem item = new OrderItem(); item.setOrderId(order.getOrderId()); item.setUserId(sequenceId); item.setOrderItemId(sequenceId); item.setStatus("创建订单"); orderItemMapper.insert(item); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); throw new RuntimeException("SQLException",e.getCause()); } return order.getOrderId(); } public OrderInfoDto selectAll(){ try { return new OrderInfoDto(orderMapper.selectAll(),orderItemMapper.selectAll()); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } @Transactional public String deleteData(long orderId){ try { orderMapper.delete(orderId); orderItemMapper.delete(orderId); return "delete data success"; } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return "failure"; } @Transactional public int updateOrder(long orderId,String status) { try { return orderMapper.update(orderId,status); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); throw new RuntimeException("exception is happenning, tx will be rollback",e.getCause()); } } public OrderInfoDto selectOrderRange(long start,long end){ try { return new OrderInfoDto(orderMapper.selectRange(start,end),null); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } public OrderInfoDto selectOrderItemRange(int start,int end){ try { return new OrderInfoDto(null,orderItemMapper.selectRange(start,end)); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } public OrderInfoDto selectOrderItemWithIn(long start,long end){ try { return new OrderInfoDto(null,orderItemMapper.selectWithInCondition(start,end)); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } public OrderInfoDto selectOrderPageList(long offset,long size){ try { return new OrderInfoDto(orderMapper.selectRange(offset,size),null); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } }
zkService Utiles:
package com.tl.it.edu.service; import com.tl.it.edu.dto.OrderInfoDto; import com.tl.it.edu.entity.Order; import com.tl.it.edu.entity.OrderItem; import com.tl.it.edu.mapper.OrderItemMapper; import com.tl.it.edu.mapper.OrderMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.sql.SQLException; /** * ,;,,; * ,;;'( 社 * __ ,;;' ' \ 会 * /' '\'~~'~' \ /'\.) 主 * ,;( ) / |. 义 *,;' \ /-.,,( ) \ 码 * ) / ) / )| 农 * || || \) * (_\ (_\ * @author :杨过 * @date :Created in 2019/11/17 17:25 * @version: V1.0 * @slogan: 天下风云出我辈,一入代码岁月催 * @description: **/ @Slf4j @Service public class OrderServiceImpl { @Autowired OrderMapper orderMapper; @Autowired OrderItemMapper orderItemMapper; @Transactional public long confirmOrder(int sequenceId){ //创建订单 Order order = new Order(); order.setAddressId(sequenceId); order.setUserId(sequenceId); order.setStatus("创建订单"); try { orderMapper.insert(order); //订单对应产品 OrderItem item = new OrderItem(); item.setOrderId(order.getOrderId()); item.setUserId(sequenceId); item.setOrderItemId(sequenceId); item.setStatus("创建订单"); orderItemMapper.insert(item); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); throw new RuntimeException("SQLException",e.getCause()); } return order.getOrderId(); } public OrderInfoDto selectAll(){ try { return new OrderInfoDto(orderMapper.selectAll(),orderItemMapper.selectAll()); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } @Transactional public String deleteData(long orderId){ try { orderMapper.delete(orderId); orderItemMapper.delete(orderId); return "delete data success"; } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return "failure"; } @Transactional public int updateOrder(long orderId,String status) { try { return orderMapper.update(orderId,status); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); throw new RuntimeException("exception is happenning, tx will be rollback",e.getCause()); } } public OrderInfoDto selectOrderRange(long start,long end){ try { return new OrderInfoDto(orderMapper.selectRange(start,end),null); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } public OrderInfoDto selectOrderItemRange(int start,int end){ try { return new OrderInfoDto(null,orderItemMapper.selectRange(start,end)); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } public OrderInfoDto selectOrderItemWithIn(long start,long end){ try { return new OrderInfoDto(null,orderItemMapper.selectWithInCondition(start,end)); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } public OrderInfoDto selectOrderPageList(long offset,long size){ try { return new OrderInfoDto(orderMapper.selectRange(offset,size),null); } catch (SQLException e) { log.info(e.getMessage(),e.getCause()); } return null; } }