关于 @Inheritance(strategy = InheritanceType.JOINED)

本文探讨了在使用InheritanceType.TABLE_PER_CLASS策略时,抽象类在实体引用中的局限性及其对数据库表结构的影响,并通过具体代码示例展示了如何正确处理继承关系。

考虑下面一种情况

建立一个“Human”类,作为抽象类。

 

 

建立一个“Employee”类,继承Human。

 

下面是一个Award类型,其中“奖励记录发布人”不能指定为任何一种具体的"human", 因此必须声明为"Human"类型。

此时如果采用的表生成策略是InheritanceType.TABLE_PER_CLASS,而非代码中所示的InheritanceType.JOINED的话,程序就无法正确运行。

根据这种表生成策略,HUMAN表里面将不会有任何信息。而AWARD表里面的外键引用的却是HUMAN表的ID。同时程序也不会知道当前的赋值给当前publisher的对象到底是存放在Employee对应的表里面还是其他Human的子类对应表里面。

 

因此,table_per_class的表生成策略,只有在抽象类不会在其他实体的代码中被引用的时候才适用。

------------------------ Bancai.java ------------------------ package com.kucun.data.entity; import java.lang.annotation.Annotation; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.Table; import com.kucun.data.entity.DTO.*; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** 板材 @author Administrator */ @Entity @Table(name=“bancai”) @JsonSerialize(using = FullEntitySerializer.class) @UniqueEntity( repositoryName = “bancai”, fields = {“houdu”, “caizhi”, “mupi1”, “mupi2”}, message = “板材组合已存在” ) public class Bancai implements EntityBasis { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne( fetch = FetchType.LAZY) @JoinColumn(name = “caizhi_id”) // private Caizhi caizhi; @ManyToOne( fetch = FetchType.LAZY) @JoinColumn(name = “mupi1_id”) private Mupi mupi1; @ManyToOne( fetch = FetchType.LAZY) @JoinColumn(name = “mupi2_id”) private Mupi mupi2; private Double houdu; @OneToOne( cascade = CascadeType.ALL, orphanRemoval = true, // 添加此配置 fetch = FetchType.LAZY ) @JoinColumn(name = “kucun_id”, referencedColumnName = “id”) private Kucun kucun; public Kucun getKucun() { return kucun; } public void setKucun(Kucun kucun) { this.kucun = kucun; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Caizhi getCaizhi() { return caizhi; } public void setCaizhi(Caizhi caizhi) { this.caizhi = caizhi; } public Mupi getMupi1() { return mupi1; } public void setMupi1(Mupi mupi1) { this.mupi1 = mupi1; } public Mupi getMupi2() { return mupi2; } public void setMupi2(Mupi mupi2) { this.mupi2 = mupi2; } public Double getHoudu() { return houdu; } public void setHoudu(Double houdu) { this.houdu = houdu; } public Bancai(int id, Caizhi caizhi, Mupi mupi1, Mupi mupi2, Double houdu) { super(); this.id = id; this.caizhi = caizhi; this.mupi1 = mupi1; this.mupi2 = mupi2; this.houdu = houdu; } public Bancai() { super(); } } ------------------------ Caizhi.java ------------------------ package com.kucun.data.entity; import java.util.List; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; import com.kucun.data.entity.DTO.UniqueEntity; /** 板材材质 @author Administrator */ @Entity @Table(name=“caizhi”, uniqueConstraints = { @UniqueConstraint(columnNames = “name”) }) @UniqueEntity( repositoryName = “caizhi”, fields = {“name”}, message = “板材组合已存在” ) @JsonSerialize(using = FullEntitySerializer.class) public class Caizhi extends SimpleEntity implements EntityBasis{ @OneToMany(mappedBy=“caizhi”) private List bancai; public List getBancai() { return bancai; } public void setBancai(List bancai) { this.bancai = bancai; } } ------------------------ Chanpin.java ------------------------ package com.kucun.data.entity; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.*; /** 产品类 @author Administrator */ @Entity @Table(name=“chanpin”, uniqueConstraints = { @UniqueConstraint(columnNames = “bianhao”) }) @JsonSerialize(using = FullEntitySerializer.class) @UniqueEntity( repositoryName = “bancai”, fields = {“bianhao”}, message = “板材组合已存在” ) public class Chanpin implements EntityBasis { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; // 关联订单产品 @OneToMany( mappedBy = “chanpin”, cascade = CascadeType.ALL, fetch = FetchType.LAZY ) private List<Dingdan_chanpin> dingdan_chanpin; private String bianhao; @OneToMany( mappedBy = "chanpin", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true ) private List<Chanpin_zujian> chanpin_zujian; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBianhao() { return bianhao; } public void setBianhao(String bianhao) { this.bianhao = bianhao; } public List<Dingdan_chanpin> getDingdan_chanpin() { return dingdan_chanpin; } public void setDingdan_chanpin(List<Dingdan_chanpin> dingdan_chanpin) { this.dingdan_chanpin = dingdan_chanpin; } public List<Chanpin_zujian> getChanpin_zujian() { return chanpin_zujian; } public void setChanpin_zujian(List<Chanpin_zujian> chanpin_zujian) { this.chanpin_zujian = chanpin_zujian; } } ------------------------ Chanpin_zujian.java ------------------------ package com.kucun.data.entity; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; import com.kucun.data.entity.DTO.UniqueEntity; /** 产品组件关联类 @author Administrator */ @Entity @Table(name=“chanpin_zujian”) @JsonSerialize(using = FullEntitySerializer.class) @UniqueEntity( repositoryName = “chanpin_zhujian”, fields = { “chanpin_id”, “zujian_id”}, message = “板材组合已存在” ) public class Chanpin_zujian implements EntityBasis { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; // 关联到产品 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = “chanpin_id”) private Chanpin chanpin; // 关联到组件 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "zujian_id") private Zujian zujian; // 关联到板材 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "bancai_id") private Bancai bancai; private Double one_howmany; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Chanpin getChanpin() { return chanpin; } public void setChanpin(Chanpin chanpin) { this.chanpin = chanpin; } public Zujian getZujian() { return zujian; } public void setZujian(Zujian zujian) { this.zujian = zujian; } public Bancai getBancai() { return bancai; } public void setBancai(Bancai bancai) { this.bancai = bancai; } public Double getOne_howmany() { return one_howmany; } public void setOne_howmany(Double one_howmany) { this.one_howmany = one_howmany; } public Chanpin_zujian() { super(); // TODO Auto-generated constructor stub } } ------------------------ Dingdan.java ------------------------ package com.kucun.data.entity; import java.util.Date; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; /** 订单 @author Administrator */ @Entity @Table(name=“dingdan”, uniqueConstraints = { @UniqueConstraint(columnNames = “number”) }) @JsonSerialize(using = FullEntitySerializer.class) public class Dingdan implements EntityBasis{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; //订单号 private String number; private Date xiadan; private Date jiaohuo; @OneToMany( mappedBy = “dingdan”, cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true ) private List<Dingdan_chanpin> dingdan_chanpin; // 优化订单与订单组件关联 @OneToMany( mappedBy = “dingdan”, cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true ) private List<Dingdan_chanpin_zujian> dingdan_chanpins_zujians; public Date getXiadan() { return xiadan; } public void setXiadan(Date xiadan) { this.xiadan = xiadan; } public Date getJiaohuo() { return jiaohuo; } public void setJiaohuo(Date jiaohuo) { this.jiaohuo = jiaohuo; } public List<Dingdan_chanpin_zujian> getDingdan_chanpins_zujians() { return dingdan_chanpins_zujians; } public void setDingdan_chanpins_zujians(List<Dingdan_chanpin_zujian> dingdan_chanpins_zujians) { this.dingdan_chanpins_zujians = dingdan_chanpins_zujians; } public List<Dingdan_chanpin> getDingdan_chanpin() { return dingdan_chanpin; } public void setDingdan_chanpin(List<Dingdan_chanpin> dingdan_chanpins) { this.dingdan_chanpin = dingdan_chanpins; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Dingdan(Integer id, String number) { super(); this.id = id; this.number = number; } public Dingdan() { super(); // TODO Auto-generated constructor stub } } ------------------------ Dingdan_chanpin.java ------------------------ package com.kucun.data.entity; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; /** 订单和产品关联 @author Administrator */ @Entity @Table(name=“dingdan_chanpin”) @JsonSerialize(using = FullEntitySerializer.class) public class Dingdan_chanpin implements EntityBasis { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; //产品信息 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = “dingdan_id”) // 指 private Dingdan dingdan; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "chanpin_id") // 指 private Chanpin chanpin; private Integer shuliang;//产品数量; public Chanpin getChanpin() { return chanpin; } public void setChanpin(Chanpin chanpin) { this.chanpin = chanpin; } public Integer getShuliang() { return shuliang; } public void setShuliang(Integer shuliang) { this.shuliang = shuliang; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Dingdan getDingdan() { return dingdan; } public void setDingdan(Dingdan dingdan) { this.dingdan = dingdan; } public Chanpin getChanping() { return chanpin; } public void setChanping(Chanpin chanping) { this.chanpin = chanping; } } ------------------------ Dingdan_chanpin_bancai.java ------------------------ package com.kucun.data.entity; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Dingdan_chanpin_bancai implements EntityBasis { @Id private Integer id; private Dingdan_chanpin dingdan_chanpin; private Bancai bancai; private Integer shuliang; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Dingdan_chanpin getDingdan_chanpin() { return dingdan_chanpin; } public void setDingdan_chanpin(Dingdan_chanpin dingdan_chanpin) { this.dingdan_chanpin = dingdan_chanpin; } public Bancai getBancai() { return bancai; } public void setBancai(Bancai bancai) { this.bancai = bancai; } public Integer getShuliang() { return shuliang; } public void setShuliang(Integer shuliang) { this.shuliang = shuliang; } public Dingdan_chanpin_bancai(Integer id, Dingdan_chanpin dingdan_chanpin, Bancai bancai, Integer shuliang) { super(); this.id = id; this.dingdan_chanpin = dingdan_chanpin; this.bancai = bancai; this.shuliang = shuliang; } public Dingdan_chanpin_bancai() { super(); // TODO Auto-generated constructor stub } } ------------------------ Dingdan_chanpin_zujian.java ------------------------ package com.kucun.data.entity; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; /** 一个订单中的产品组件订购板材数量 @author Administrator */ @Entity @JsonSerialize(using = FullEntitySerializer.class) public class Dingdan_chanpin_zujian implements EntityBasis{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dingdan_id") // 指定外键列 private Dingdan dingdan; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "chanpin_zujian_id") // 指定外键列 private Chanpin_zujian chanpin_zujian; // 修改为单数形式 //板材 @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "bancai_id") private Bancai bancai; //订购数 private Integer shuliang ; public Dingdan_chanpin_zujian() { super(); // TODO Auto-generated constructor stub } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Dingdan getDingdan() { return dingdan; } public void setDingdan(Dingdan dingdan) { this.dingdan = dingdan; } public Bancai getBancai() { return bancai; } public void setBancai(Bancai bancai) { this.bancai = bancai; } public Chanpin_zujian getChanpin_zujian() { return chanpin_zujian; } public void setChanpin_zujian(Chanpin_zujian chanpin_zujian) { this.chanpin_zujian = chanpin_zujian; } public Integer getShuliang() { return shuliang; } public void setShuliang(Integer shuliang) { this.shuliang = shuliang; } } ------------------------ EntityBasis.java ------------------------ package com.kucun.data.entity; public interface EntityBasis { Integer getId(); void setId(Integer id); } ------------------------ Information.java ------------------------ package com.kucun.data.entity; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; /** 通信类 @author Administrator */ public class Information { private static final ObjectMapper mapper = new ObjectMapper(); private Integer Status ; private String text; private Object data; public Integer getStatus() { return Status; } public void setStatus(Integer status) { Status = status; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public Information(Integer status, String text, Object data) { super(); Status = status; this.text = text; this.data = data; } @SuppressWarnings({“unchecked”,“rawtypes”}) public Information(Integer status, String text, String data, Class T) throws Exception { super(); Status = status; this.text = text; this.data = fromJson(data,T); } public Information() { super(); // TODO Auto-generated constructor stub } public String DataJson() throws JsonProcessingException { // Java对象转JSON return mapper.writeValueAsString(this); } @SuppressWarnings(“unchecked”) public T fromJson(String json, Class clazz) throws Exception { data= mapper.readValue(json, clazz); return (T) data; } public static Information NewSuccess(Object data) { return new Information(200, "success", data); } public static Information NewSuccess(String data) { return new Information(200, "success", data); } public static Information Newfail(Integer status,String text,Object data) { return new Information(status, "success", data); } public static Information NewFail(int i, String string) { // TODO Auto-generated method stub return new Information(i,string,null); } public static Information NewFail( String string) { // TODO Auto-generated method stub return new Information(400,string,null); } } ------------------------ Jinhuo.java ------------------------ package com.kucun.data.entity; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; @Entity @JsonSerialize(using = FullEntitySerializer.class) public class Jinhuo implements EntityBasis{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne private Dingdan dingdan; @ManyToOne private Chanpin chanpin; @ManyToOne private Zujian zujian; @ManyToOne private Bancai bancai; private Integer shuliang; private Date date; @ManyToOne private User user; public Jinhuo(Integer id, Dingdan dingdan, Chanpin chanpin, Zujian zujian, Bancai bancai, Integer shuliang, Date date, User user) { super(); this.id = id; this.dingdan = dingdan; this.chanpin = chanpin; this.zujian = zujian; this.bancai = bancai; this.shuliang = shuliang; this.date = date; this.user = user; } public Jinhuo() { super(); // TODO Auto-generated constructor stub } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Dingdan getDingdan() { return dingdan; } public void setDingdan(Dingdan dingdan) { this.dingdan = dingdan; } public Chanpin getChanpin() { return chanpin; } public void setChanpin(Chanpin chanpin) { this.chanpin = chanpin; } public Zujian getZujian() { return zujian; } public void setZujian(Zujian zujian) { this.zujian = zujian; } public Bancai getBancai() { return bancai; } public void setBancai(Bancai bancai) { this.bancai = bancai; } public Integer getShuliang() { return shuliang; } public void setShuliang(Integer shuliang) { this.shuliang = shuliang; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } ------------------------ Kucun.java ------------------------ package com.kucun.data.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; /** 库存 @author Administrator */ @Entity @JsonSerialize(using = FullEntitySerializer.class) public class Kucun implements EntityBasis{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Integer shuliang; @OneToOne(fetch = FetchType.LAZY) // 正确映射 Bancai 实体 @JoinColumn(name = "bancai_id", referencedColumnName = "id") private Bancai bancai; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Bancai getBancai() { return bancai; } public void setBancai(Bancai bancai) { this.bancai = bancai; } public Integer getShuliang() { return shuliang; } public void setShuliang(Integer shuliang) { this.shuliang = shuliang; } public Kucun(Integer id, Bancai bancai, Integer shuliang) { super(); this.id = id; this.bancai = bancai; this.shuliang = shuliang; } public Kucun() { super(); // TODO Auto-generated constructor stub } } ------------------------ Mupi.java ------------------------ package com.kucun.data.entity; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import org.hibernate.annotations.Type; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; /** 木皮 @author Administrator */ @Entity @Table(name=“mupi”, uniqueConstraints = { @UniqueConstraint(columnNames = “name”) }) @JsonSerialize(using = FullEntitySerializer.class) public class Mupi extends SimpleEntity implements EntityBasis{ /** * 是否有油漆 */ @Column(name="you") @Type(type = "org.hibernate.type.BooleanType") private Boolean you; // 添加 OneToMany 映射 @OneToMany(mappedBy = "mupi1") // 指向 Bancai 中的 mupi1 字段 private List<Bancai> bancaisForMupi1; @OneToMany(mappedBy = "mupi2") // 指向 Bancai 中的 mupi2 字段 private List<Bancai> bancaisForMupi2; public List<Bancai> getBancaisForMupi1() { return bancaisForMupi1; } public void setBancaisForMupi1(List<Bancai> bancaisForMupi1) { this.bancaisForMupi1 = bancaisForMupi1; } public List<Bancai> getBancaisForMupi2() { return bancaisForMupi2; } public void setBancaisForMupi2(List<Bancai> bancaisForMupi2) { this.bancaisForMupi2 = bancaisForMupi2; } public Mupi() { super(); } public Boolean getYou() { return you; } public void setYou(Boolean you) { this.you = you; } } ------------------------ SimpleEntity.java ------------------------ package com.kucun.data.entity; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; @MappedSuperclass public abstract class SimpleEntity implements EntityBasis{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(nullable = false, unique = true) private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // Getters and Setters... } ------------------------ User.java ------------------------ package com.kucun.data.entity; import java.util.Objects; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; /** 用户 @author Administrator / @Entity @Table(name=“user”) @JsonSerialize(using = FullEntitySerializer.class) public class User implements EntityBasis{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; /* * 名字 / @Column(nullable=false) private String name; /* * 账号 / @Column(nullable=false) private String andy; /* * 密码 / @Column(nullable=false) private String pass; /* * 权限 */ @Column(nullable=false) private int role; public User() { super(); } public User(int id, String name, String andy, String pass) { super(); this.id = id; this.name = name; this.andy = andy; this.pass = pass; } public Integer getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAndy() { return andy; } public void setAndy(String andy) { this.andy = andy; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } public int getRole() { System.out.println(role); return role; } public void setRole(int role) { this.role = role; } @Override public String toString() { return "{id:" + id + ", name:" + name + ", andy:" + andy + ", pass:" + pass + ", role:" + role + "}"; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return Objects.equals(id, user.id) && Objects.equals(name, user.name) && Objects.equals(andy, user.andy)&& Objects.equals(role, user.role); //添加所有属性比较 } @Override public int hashCode() { return Objects.hash(id, name, andy,pass,role); } @Override public void setId(Integer id) { // TODO Auto-generated method stub } } ------------------------ Zujian.java ------------------------ package com.kucun.data.entity; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.OneToMany; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; @Entity @JsonSerialize(using = FullEntitySerializer.class) public class Zujian extends SimpleEntity implements EntityBasis{ // 反向关联到产品组件 @OneToMany( mappedBy = "zujian", cascade = CascadeType.ALL, fetch = FetchType.LAZY ) private List<Chanpin_zujian> chanping_zujian; public List<Chanpin_zujian> getChanping_zujian() { return chanping_zujian; } public void setChanping_zujian(List<Chanpin_zujian> chanping_zujian) { this.chanping_zujian = chanping_zujian; } } 设计改造一个数据结构, 要求 一个订单有很多产品不同数量,每个产品可以再很多订单中,一个产品有很多组件,一个组件可以在很多产品中,因为每个组件因为在不同的产品中有不同的生产工艺,所以使用不同的板材和板材能生产组件数量,每个板材有不同的材质和两面木皮,木皮表面可能有油漆, 订购时可能直接购入板材,也可能按订单和产品订购,也用可能按订单产品组件订购 ,每次采购不标准,一个订单可能订购几次,用户有姓名 账号 密码 权限, 一个记录进货和消耗
06-23
<think>我们有一个现有的数据结构,涉及订单、产品、组件、板材、材质、木皮、库存、进货等实体。现在需要设计一个改造方案,满足以下要求:1.一个订单有很多产品(不同数量),每个产品可以在多个订单中。2.一个产品有很多组件,一个组件可以在多个产品中。3.每个组件在不同的产品中可能使用不同的板材(因为生产工艺不同),并且每个组件使用特定板材时,能生产的数量(即一个组件需要多少板材)也是不同的。4.每个板材有不同的材质和两面木皮(木皮表面可能有油漆)。5.订购方式多样:可能直接购入板材,也可能按订单和产品订购,还可能按订单产品组件订购。6.采购不标准:一个订单可能分多次采购(进货)。7.用户有姓名、账号、密码、权限。现有代码中已经有一些实体,但可能需要进行改造。我们将分析现有实体并进行必要的调整。现有实体分析:-Bancai(板材):包含id、材质(caizhi)、木皮1(mupi1)、木皮2(mupi2)、厚度(houdu)和库存(kucun)的一对一关联。-Caizhi(材质):包含id、name,以及关联的板材列表。-Chanpin(产品):包含id、编号(bianhao),以及关联的订单产品列表(dingdan_chanpin)和产品组件列表(chanpin_zujian)。-Chanpin_zujian(产品组件关联):包含id、关联的产品(chanpin)、关联的组件(zujian)、关联的板材(bancai)以及一个组件需要多少板材(one_howmany)。-Dingdan(订单):包含id、订单号(number)、下单日期(xiadan)、交货日期(jiaohuo),以及关联的订单产品列表(dingdan_chanpin)和订单产品组件列表(dingdan_chanpins_zujians)。-Dingdan_chanpin(订单产品关联):包含id、订单(dingdan)、产品(chanpin)和数量(shuliang)。-Dingdan_chanpin_zujian(订单产品组件关联):包含id、订单(dingdan)、产品组件关联(chanpin_zujian)、板材(bancai)和数量(shuliang)。注意:这里直接关联了产品组件关联(Chanpin_zujian),然后关联到板材和数量。但这里有一个问题:在订单中,我们可能直接订购某个产品组件的板材,但数量是独立于产品组件关联中定义的数量的(因为订购数量是订单决定的)。-Jinhuo(进货):包含id、订单(dingdan)、产品(chanpin)、组件(zujian)、板材(bancai)、数量(shuliang)、日期(date)和用户(user)。这里似乎试图记录多种类型的进货(按订单、产品、组件、板材)。但这样设计可能过于宽泛,需要重新考虑。-Kucun(库存):包含id、板材(bancai)和数量(shuliang)。每个板材对应一个库存记录。-Mupi(木皮):包含id、name、是否有油漆(you),以及关联的板材(作为mupi1和mupi2)。-User(用户):包含id、姓名(name)、账号(andy)、密码(pass)、权限(role)。-Zujian(组件):包含id、name,以及关联的产品组件列表(chanping_zujian)。改造思路:1.订购方式多样性的处理:-直接购入板材:只需要记录进货的板材和数量,不关联订单、产品、组件。-按订单和产品订购:进货关联订单和产品,但不关联组件和板材(因为产品由多个组件组成,可能使用多种板材,但按产品订购时,我们可能不知道具体板材?所以这种订购方式可能不直接,或者需要进一步拆分)。-按订单产品组件订购:进货关联订单、产品、组件和板材,以及数量。2.采购不标准:一个订单可能分多次进货。因此,进货记录应该独立于订单,但可以关联到订单(如果该进货是针对某个订单的)。3.进货记录需要区分不同的订购方式,我们可以通过允许某些关联字段为空来实现。例如:-如果是直接购入板材,则订单、产品、组件为空,只填板材和数量。-如果是按订单产品订购,则组件为空,填写订单、产品和板材(但这里按产品订购,可能无法具体到板材,因为一个产品包含多个组件,每个组件可能用不同板材。所以按产品订购可能并不合适,或者需要理解为该产品所需的所有板材?但这样又太模糊。因此,可能需要取消按产品订购,只允许按板材或按产品组件订购)。4.考虑到实际业务,我们可能更倾向于:-直接购入板材(不关联订单)。-按订单产品组件订购(关联订单、产品、组件、板材和数量)。5.但是,在进货记录中,我们可能还需要记录是用于哪个订单的哪个产品的哪个组件,所以进货记录应该关联到订单、产品、组件和板材。这里的产品和组件信息可以通过产品组件关联(Chanpin_zujian)来获取,但进货时可能不需要完全按照产品组件关联中指定的板材(比如临时更换板材),所以进货记录中需要明确记录使用的板材。6.因此,我们改造进货实体(Jinhuo)如下:-保留关联订单(dingdan)、产品(chanpin)、组件(zujian)、板材(bancai)和数量(shuliang)。-但是,注意:一个进货记录可能只关联到订单(如果是按订单整体进货?但订单整体进货又无法具体到组件和板材)?所以,我们可能需要规定进货记录必须关联到具体的板材,并且可以关联到订单、产品、组件(可选)。7.实际上,进货的最小单位是板材,所以每一条进货记录都应该有板材和数量。同时,为了追踪该板材用于什么订单、什么产品、什么组件,我们关联订单、产品、组件(可以为空,表示直接购入的板材,不用于特定订单、产品或组件)。8.因此,Jinhuo实体可以设计为:-id-订单(dingdan)->可为空-产品(chanpin)->可为空-组件(zujian)->可为空-板材(bancai)->非空-数量(shuliang)->非空-日期(date)-用户(user)->记录操作者9.这样,当进货是直接购入板材时,订单、产品、组件都为空,只记录板材和数量。当进货是针对某个订单的某个产品的某个组件时,就关联订单、产品、组件和板材。10.但是,这里有一个问题:同一个订单的同一个产品的同一个组件可能使用多种板材(比如不同批次),所以这样设计可以支持。11.另外,在订单产品组件关联(Dingdan_chanpin_zujian)中,我们记录了某个订单中某个产品组件的订购板材和数量。这个数量应该是该订单中该产品组件需要的该板材的总数量。而进货记录中,每次进货的数量是实际到货的数量,累计进货数量不应超过订购数量(但可能超过,因为可能多购,或者独立购入)。12.库存(Kucun)是独立存在的,每次进货都会增加库存,而生产消耗会减少库存。库存只关联板材,不关联订单、产品等。13.生产消耗:当订单生产时,会消耗库存。我们需要记录消耗(即出库)。目前没有出库实体,需要添加。出库记录可以类似于进货记录,但数量为负?或者单独建立出库记录实体。为了清晰,我们可以建立ChuKu(出库)实体,结构与Jinhuo类似,但也可以考虑将进货和出库统一为一个库存变更记录实体(StockChange),并有一个类型字段(进货/出库)。14.考虑到扩展性,我们可以创建库存变更记录实体(StockChange):-id-变更类型(type:IN/OUT)-关联订单(dingdan,可为空)-关联产品(chanpin,可为空)-关联组件(zujian,可为空)-板材(bancai,非空)-数量(shuliang,非空,正数表示进货,负数表示出库?或者用正数,然后根据类型判断增减)-日期(date)-用户(user)但是,这样设计的话,我们如何区分是进货还是出库?可以有一个枚举字段表示类型(IN,OUT),数量始终为正数,然后根据类型决定是增加还是减少库存。15.或者,我们可以分开进货和出库,因为它们的业务含义不同。但为了统一查询库存流水,合并为一个实体更便于管理。16.因此,我们建议新增一个库存变更实体(StockChange),并修改Jinhuo实体为StockChange,同时添加一个类型字段。17.但是,由于现有代码中已有Jinhuo,并且可能已有数据,所以我们可以选择重构Jinhuo为StockChange,并调整相关代码。18.考虑到时间,我们暂时不改变现有表结构,而是先按照要求调整。由于问题要求改造数据结构,我们可以重新设计。19.重新设计库存变更记录(StockChange):```javapackagecom.kucun.data.entity;importjavax.persistence.*;importjava.util.Date;@EntitypublicclassStockChangeimplementsEntityBasis{@Id@GeneratedValue(strategy=GenerationType.IDENTITY)privateIntegerid;@Enumerated(EnumType.STRING)privateChangeTypetype;//枚举:IN(进货),OUT(出库)@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="dingdan_id")privateDingdandingdan;//可为空@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="chanpin_id")privateChanpinchanpin;//可为空@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="zujian_id")privateZujianzujian;//可为空@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="bancai_id",nullable=false)privateBancaibancai;//非空privateIntegerquantity;//数量,正数@Temporal(TemporalType.TIMESTAMP)privateDatedate;@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="user_id")privateUseruser;//操作者//枚举类型publicenumChangeType{IN,OUT}//gettersandsetters...}```20.这样,每次进货就创建一个类型为IN的记录,出库就创建类型为OUT的记录。库存数量可以通过累加同一板材的IN记录减去OUT记录得到。21.同时,移除原有的Jinhuo实体,并将库存(Kucun)实体中的数量(shuliang)去掉,因为库存数量是动态计算的(或者保留作为缓存,但需要维护一致性,建议动态计算)。22.但是,动态计算库存可能在大数据量时性能问题,所以可以保留Kucun实体,但每次库存变更时更新Kucun表。我们可以在业务层保证一致性,或者使用触发器。23.考虑到简单性,我们暂时不保留Kucun表,而是每次查询时计算。或者,我们可以使用一个定时任务来更新Kucun表。但为了实时性,我们可以在每次库存变更时更新Kucun表。24.我们选择保留Kucun表,并在每次库存变更时更新对应板材的库存数量。这样,Kucun表作为库存快照。25.因此,我们保留Kucun实体,并添加一个方法在库存变更时更新库存数量。26.另外,关于订购记录,目前有:-Dingdan_chanpin:记录订单中的产品数量。-Dingdan_chanpin_zujian:记录订单中某个产品组件的板材订购数量。这两个表是用于记录订购需求的,而不是实际进货。实际进货记录在StockChange中。27.现在,我们考虑如何支持“按订单产品组件订购”的进货。在进货时,我们可以选择订单、产品、组件,然后选择板材和数量。这个进货数量会累加到该订单该产品组件的已进货数量中。我们可以在Dingdan_chanpin_zujian中添加一个已进货数量字段,或者通过查询StockChange来计算。28.为了减少冗余,建议通过查询StockChange来计算已进货数量。这样,我们只需要在Dingdan_chanpin_zujian中记录订购数量(计划数量),实际进货数量通过汇总StockChange(类型为IN,且关联到同一个订单、同一个产品组件、同一个板材)的数量得到。29.因此,Dingdan_chanpin_zujian实体保持不变。30.总结改造点:a.删除Jinhuo实体,新增StockChange实体(包括库存进货和消耗)。b.在StockChange中,记录每次库存变动(包括关联的订单、产品、组件、板材、数量、类型等)。c.库存数量(Kucun)由StockChange计算得到,但为了性能,我们在每次StockChange变更时更新Kucun表(在应用层用事务保证一致性)。d.进货时,如果是直接购入板材,则StockChange中的订单、产品、组件为空;如果是为某个订单的某个产品组件进货,则关联订单、产品、组件和板材。31.用户实体(User)已经满足要求。32.其他实体(Bancai,Caizhi,Chanpin,Chanpin_zujian,Dingdan,Dingdan_chanpin,Dingdan_chanpin_zujian,Mupi,Zujian)暂时保持不变。33.注意:在Dingdan_chanpin_zujian中,已经关联了订单、产品组件(Chanpin_zujian)、板材和订购数量。而产品组件(Chanpin_zujian)关联了产品、组件、板材和每个组件需要的板材数量(one_howmany)。这里,在订单产品组件订购记录(Dingdan_chanpin_zujian)中,同一个产品组件(Chanpin_zujian)可能会被订购多次(但应该在同一订单中不会重复,因为同一个产品组件的同一板材应该只记录一次),所以Dingdan_chanpin_zujian应该设计为唯一约束(订单、产品组件、板材)?目前没有唯一约束,需要添加。34.另外,在Chanpin_zujian(产品组件关联)中,同一个产品同一个组件可以关联多个板材吗?目前设计是一个产品组件关联一个板材(因为Chanpin_zujian中有一个bancai字段)。所以,一个产品的同一个组件只能使用一种板材。如果同一个组件在一个产品中需要使用多种板材,那么就需要创建多个Chanpin_zujian记录(同一个产品同一个组件关联多个板材)。这样,在订单产品组件订购记录(Dingdan_chanpin_zujian)中,就可以针对不同的板材分别记录订购数量。35.因此,现有设计已经支持一个产品的同一个组件使用多种板材。36.但是,在Dingdan_chanpin_zujian中,关联的是Chanpin_zujian,然后Chanpin_zujian关联了具体的板材。那么,在进货时,我们是否应该直接关联到Dingdan_chanpin_zujian?这样,进货记录就知道是为哪个订单产品组件关联记录进货的。但注意:进货时可能并不严格按照订购的板材进货(比如更换板材),所以进货记录中应该直接记录板材,而不是通过Chanpin_zujian间接关联板材。37.在StockChange中,我们直接关联了板材,所以即使更换板材,也可以直接记录。同时,我们关联了订单、产品、组件(如果知道的话),这样我们就可以追踪到该进货是用于哪个订单的哪个产品的哪个组件,即使没有通过Chanpin_zujian。38.但是,如果严格按照订购的板材进货,那么进货记录中的产品、组件、板材应该与订购记录(Dingdan_chanpin_zujian)中的一致。为了建立联系,我们可以在StockChange中关联Dingdan_chanpin_zujian(订单产品组件订购记录)。这样,我们就知道这次进货是为了满足哪一条订购记录。39.然而,这样设计可能过于死板,因为实际进货可能无法严格对应到订购记录(比如一次进货满足多个订购记录)。所以,我们不强制关联,而是通过业务逻辑来处理。40.因此,StockChange设计为:-关联订单、产品、组件、板材(可选),以及数量、类型等。41.最后,给出StockChange实体的代码:42.由于需要删除Jinhuo,所以原有Jinhuo相关代码需要移除。43.另外,我们还需要一个服务或监听器,在每次保存StockChange时更新Kucun表(对应板材的库存数量)。可以通过SpringDataJPA的@EventListener或使用Service层事务提交后更新。44.考虑到时间,我们先给出StockChange实体代码,并假设库存更新由服务层保证。45.代码实现:新增StockChange实体:```javapackagecom.kucun.data.entity;importjavax.persistence.*;importjava.util.Date;@Entity@Table(name="stock_change")publicclassStockChangeimplementsEntityBasis{publicenumChangeType{IN,//进货OUT//出库(消耗)}@Id@GeneratedValue(strategy=GenerationType.IDENTITY)privateIntegerid;@Enumerated(EnumType.STRING)@Column(nullable=false)privateChangeTypetype;@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="dingdan_id")privateDingdandingdan;//可为空@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="chanpin_id")privateChanpinchanpin;//可为空@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="zujian_id")privateZujianzujian;//可为空@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="bancai_id",nullable=false)privateBancaibancai;//非空@Column(nullable=false)privateIntegerquantity;//变更数量,正数@Temporal(TemporalType.TIMESTAMP)@Column(nullable=false)privateDatedate;@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="user_id",nullable=false)privateUseruser;//操作者//gettersandsetters...@OverridepublicIntegergetId(){returnid;}@OverridepublicvoidsetId(Integerid){this.id=id;}publicChangeTypegetType(){returntype;}publicvoidsetType(ChangeTypetype){this.type=type;}publicDingdangetDingdan(){returndingdan;}publicvoidsetDingdan(Dingdandingdan){this.dingdan=dingdan;}publicChanpingetChanpin(){returnchanpin;}publicvoidsetChanpin(Chanpinchanpin){this.chanpin=chanpin;}publicZujiangetZujian(){returnzujian;}publicvoidsetZujian(Zujianzujian){this.zujian=zujian;}publicBancaigetBancai(){returnbancai;}publicvoidsetBancai(Bancaibancai){this.bancai=bancai;}publicIntegergetQuantity(){returnquantity;}publicvoidsetQuantity(Integerquantity){this.quantity=quantity;}publicDategetDate(){returndate;}publicvoidsetDate(Datedate){this.date=date;}publicUsergetUser(){returnuser;}publicvoidsetUser(Useruser){this.user=user;}}```46.同时,我们需要修改Kucun实体,并确保在每次StockChange保存时更新对应板材的库存。这可以通过在StockChangeRepository保存时触发KucunService.updateStock方法来实现。47.由于这是一个较大的改动,且涉及事务和性能,具体实现细节可能超出数据结构设计范围。因此,我们只给出数据结构改造。48.最后,移除原有的Jinhuo实体。49.另外,在Dingdan_chanpin_zujian中,我们记录了订购数量,这个数量是计划使用的数量。实际进货数量通过StockChange(类型为IN,关联同一订单、产品、组件、板材)汇总得到。消耗(出库)同理。50.这样,我们就满足了要求。由于问题要求给出代码并解释,我们只给出了新增的StockChange实体代码,并解释了改造思路。其他实体保持不变。注意:以上设计是一种方案,具体实现时还需要根据业务需求调整。现在,根据要求,在最后提出相关问题。§§相关问题§§:1.如何确保库存变更时更新库存表(Kucun)的一致性?2.在按订单产品组件订购时,如何避免重复进货(超过订购数量)?3.如何查询某个订单的进货进度?4.如何计算当前库存中某个板材的总数量?</think>### 数据结构改造分析 根据需求,现有数据结构需要支持以下核心场景: 1. 订单-产品多对多关系(不同数量) 2. 产品-组件多对多关系 3. 组件-板材关联(带生产工艺参数) 4. 多种订购方式(板材/产品/组件级) 5. 多次采购记录 6. 用户权限管理 7. 库存动态管理 ### 主要问题及改进方案 #### 1. 组件-板材关联优化 **问题**:`Chanpin_zujian` 中直接关联 `Bancai` 限制了组件在不同产品中使用不同板材的能力 **解决方案**:引入中间表 `Zujian_Bancai` 存储组件-板材的生产关系 ```java @Entity @Table(name = "zujian_bancai") public class ZujianBancai implements EntityBasis { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "zujian_id") private Zujian zujian; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "bancai_id") private Bancai bancai; // 生产工艺参数 private Double yieldRate; // 成品率 private String processNote; // 工艺说明 // Getters and setters } ``` #### 2. 订单订购结构优化 **问题**:现有 `Dingdan_chanpin_zujian` 直接关联板材,缺少灵活性 **解决方案**:三级订购体系 ```java // 1. 订单-产品关联(不变) @Entity public class Dingdan_chanpin { ... } // 2. 新增订单-产品-组件关联 @Entity @Table(name = "dingdan_chanpin_zujian") public class DingdanChanpinZujian { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dingdan_chanpin_id") private Dingdan_chanpin dingdanChanpin; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "chanpin_zujian_id") private Chanpin_zujian chanpinZujian; private Integer quantity; // 组件数量 // Getters and setters } // 3. 订单-组件-板材关联 @Entity @Table(name = "dingdan_zujian_bancai") public class DingdanZujianBancai { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dingdan_chanpin_zujian_id") private DingdanChanpinZujian dingdanChanpinZujian; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "zujian_bancai_id") private ZujianBancai zujianBancai; private Integer quantity; // 板材消耗量 // Getters and setters } ``` #### 3. 采购记录重构 **问题**:`Jinhuo` 实体字段冗余 **解决方案**:使用多态关联 ```java @Entity @Inheritance(strategy = InheritanceType.JOINED) public abstract class Procurement implements EntityBasis { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Integer quantity; private Date date; @ManyToOne(fetch = FetchType.LAZY) private User user; // Getters and setters } // 板材级采购 @Entity public class BancaiProcurement extends Procurement { @ManyToOne(fetch = FetchType.LAZY) private Bancai bancai; } // 产品级采购 @Entity public class ChanpinProcurement extends Procurement { @ManyToOne(fetch = FetchType.LAZY) private Chanpin chanpin; @ManyToOne(fetch = FetchType.LAZY) private Dingdan dingdan; // 可选 } // 组件级采购 @Entity public class ZujianProcurement extends Procurement { @ManyToOne(fetch = FetchType.LAZY) private Zujian zujian; @ManyToOne(fetch = FetchType.LAZY) private Dingdan dingdan; // 可选 } ``` #### 4. 库存动态计算优化 **问题**:`Kucun` 表需要实时更新 **解决方案**:改为视图 + 快照 ```sql -- 创建库存视图 CREATE VIEW v_kucun AS SELECT b.id AS bancai_id, COALESCE(SUM(p.quantity), 0) - COALESCE(( SELECT SUM(dz.quantity) FROM dingdan_zujian_bancai dz WHERE dz.zujian_bancai_id IN ( SELECT zb.id FROM zujian_bancai zb WHERE zb.bancai_id = b.id ) ), 0) AS current_stock FROM bancai b LEFT JOIN procurement p ON p.bancai_id = b.id GROUP BY b.id; ``` ```java // 库存快照实体(定时任务更新) @Entity public class KucunSnapshot implements EntityBasis { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @OneToOne(fetch = FetchType.LAZY) private Bancai bancai; private Integer quantity; private Date snapshotDate; // Getters and setters } ``` #### 5. 用户权限增强 **问题**:`User.role` 权限控制不足 **解决方案**:引入RBAC模型 ```java @Entity public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; // ADMIN, PURCHASE, SALES, etc. } @Entity public class Permission { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String resource; // ORDER, PRODUCT, INVENTORY, etc. private String action; // CREATE, READ, UPDATE, DELETE } @Entity public class User { // ... 现有字段 @ManyToMany @JoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) private Set<Role> roles = new HashSet<>(); } // 角色-权限关联 @Entity public class RolePermission { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne private Role role; @ManyToOne private Permission permission; } ``` ### 改进后数据结构优势 1. **灵活性**:支持组件在不同产品中使用不同板材 2. **可追溯性**:三级订购体系完整记录物料需求 3. **采购多样性**:支持三种采购模式 4. **权限控制**:RBAC实现精细权限管理 5. **库存效率**:视图+快照解决实时性与性能矛盾 ### 关键关联示意图 ``` 订单(Dingdan) └─○ 订单产品(Dingdan_chanpin) [1:N] └─○ 订单组件(DingdanChanpinZujian) [1:N] └─○ 板材需求(DingdanZujianBancai) [1:1] └─ 板材(Bancai) 组件(Zujian) └─○ 组件-板材(ZujianBancai) [1:N] └─ 板材(Bancai) 采购(Procurement) ├─ 板材采购(BancaiProcurement) ├─ 产品采购(ChanpinProcurement) └─ 组件采购(ZujianProcurement) ``` ### 示例查询:获取订单板材需求 ```java public List<BancaiRequirementDTO> getOrderBancaiRequirements(Integer orderId) { String jpql = "SELECT NEW com.kucun.data.dto.BancaiRequirementDTO(" + "b.id, b.caizhi.name, b.mupi1.name, b.mupi2.name, b.houdu, " + "SUM(dzb.quantity)) " + "FROM DingdanZujianBancai dzb " + "JOIN dzb.zujianBancai zb " + "JOIN zb.bancai b " + "WHERE dzb.dingdanChanpinZujian.dingdanChanpin.dingdan.id = :orderId " + "GROUP BY b.id"; TypedQuery<BancaiRequirementDTO> query = em.createQuery(jpql, BancaiRequirementDTO.class); query.setParameter("orderId", orderId); return query.getResultList(); } ``` ### 总结 改造后的数据结构: 1. 通过 `ZujianBancai` 解耦组件与板材关系 2. 三级订购体系 (`Dingdan→Dingdan_chanpin→DingdanChanpinZujian→DingdanZujianBancai`) 实现精细化管理 3. 多态采购 (`Procurement` 继承体系) 支持多种采购场景 4. RBAC 权限模型增强系统安全性 5. 物化视图 + 快照优化库存查询性能 此设计满足所有需求场景,同时保持数据的完整性和查询效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值