4

I've got inheritance working but it's not very DRY. Every new bolt type I have to repeat code. Best to show my classes then explain further

My parent class for a BoltSpec (Dimensions pertaining to a fastener)

@Entity
@Table(name="BoltSpecs")
@IdClass(BoltSpecCK.class)
@DiscriminatorColumn(name="boltType" )
public abstract class BoltSpec implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private String size;

    @Id
    @Enumerated(EnumType.STRING)
    private EnumBoltType boltType;

    private BigDecimal basic_major_diameter = BigDecimal.ZERO;

and my EnumBoltType

public enum EnumBoltType {
    CYLINDER_HEAD_CAP_SCREW("CYLINDER HEAD CAP SCREW", EnumHeadType.CYL),
    HEX_CAP_SCREW("HEX CAP SCREW", EnumHeadType.HEX),
    HEAVY_HEX_CAP_SCREW("HEAVY HEX CAP SCREW", EnumHeadType.HEX),
    HEX_BOLT("HEX BOLT", EnumHeadType.HEX),
    HEAVY_HEX_BOLT("HEAVY HEX BOLT", EnumHeadType.HEX),
    FLAT_COUNTERSUNK_HEAD_CAP_SCREW("FLAT COUNTERSUNK HEAD CAP SCREW", EnumHeadType.CONE);

I then have to have duplicate classes, i.e. HexCapScrew, HeavyHexCapScrew etc and HexCapScrewSpec, HeavyHexCapScrewSpec, etc even though they have similar BoltSpec Properties (not numerical values)

public class HexCapScrew extends Bolt {
    private static final long serialVersionUID = 1L;
    private static HexCapScrewSpec spec;
    public HexCapScrew() {
        super(spec);
    }
}

public class HeavyHexCapScrew extends Bolt {
    private static final long serialVersionUID = 1L;
    private static HeavyHexCapScrewSpec spec;
    public HeavyHexCapScrew () {
        super(spec);
    }
}

...

@Entity
@DiscriminatorValue("HEX_CAP_SCREW")
public class HexCapScrewSpec extends BoltSpec implements Serializable {
    private static final long serialVersionUID = 1L;

    public HexCapScrewSpec() {
        super();
    }

    private BigDecimal flat_diameter = BigDecimal.ZERO;
    ...

@Entity
@DiscriminatorValue("HEAVY_HEX_CAP_SCREW")
public class HeavyHexCapScrewSpec extends BoltSpec implements Serializable {
    private static final long serialVersionUID = 1L;

    public HeavyHexCapScrewSpec() {
        super();
    }

    private BigDecimal flat_diameter = BigDecimal.ZERO;
    ...

this spec is different

@Entity
@DiscriminatorValue("FLAT_COUNTERSUNK_HEAD_CAP_SCREW")
public class FlatHeadCapScrewSpec extends BoltSpec implements Serializable {
    private static final long serialVersionUID = 1L;

    public FlatHeadCapScrewSpec() {
        super();
    }

    private BigDecimal cone_angle = BigDecimal.ZERO;
    ...

here is some sample import.sql data

insert into BoltSpecs (basic_size, basic_major_diameter, boltType, flat_diameter) 
    values ('2-3/4', '2.75',  'HEX_CAP_SCREW',       '3.988')
    values ('3',     '3',     'HEX_CAP_SCREW',       '4.35')
    values ('3/8',   '0.375', 'HEAVY_HEX_CAP_SCREW', '0.669')

insert into BoltSpecs (basic_size, basic_major_diameter, boltType, cone_angle) 
    values ('2-3/4', '2.75',  'FLAT_COUNTERSUNK_HEAD_CAP_SCREW',       '39.77')

I have in the frontend a dropdown menu where the user chooses the bolt type and need to use the applicable bolt specs. I don't want to modify my import.sql and put the bolt head type. I run the risk of putting say CONE for a HEX type bolt. Is there a way to do multiple DiscriminatorValues? Like:

@Entity
@DiscriminatorValue("HEX_CAP_SCREW, HEAVY_HEX_CAP_SCREW, HEX_BOLT, HEAVY_HEX_BOLT")
public class BoltSpecHexHead extends BoltSpec implements Serializable {
    private static final long serialVersionUID = 1L;

    public BoltSpecHexHead () {
        super();
    }

    private BigDecimal flat_diameter = BigDecimal.ZERO;

...

public class BoltHexHead extends Bolt {
    private static final long serialVersionUID = 1L;
    private static BoltSpecHexHead spec;
    public BoltSpecHexHead () {
        super(spec);
    }
}

Or how can I ping off the EnumHeadType as the discriminator value? Specifications are similar between bolts with similar heads (EnumHeadType.CYL, HEX and CONE)

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
jeff
  • 3,618
  • 9
  • 48
  • 101

2 Answers2

0

I was able to achieve a solution using @DiscriminatorFormula

@Entity
@Table(name="BoltSpecs")
@IdClass(BoltSpecCK.class)
//@DiscriminatorColumn(name="boltType" )
@DiscriminatorFormula("case when boltType in ('CYLINDER_HEAD_CAP_SCREW') then 'HEX' 
   when boltType in ('HEX_CAP_SCREW','HEAVY_HEX_CAP_SCREW','HEX_BOLT','HEAVY_HEX_BOLT') then 'HEX' 
   when boltType in ('FLAT_COUNTERSUNK_HEAD_CAP_SCREW') then 'CONE' end")

public abstract class BoltSpec implements Serializable {
jeff
  • 3,618
  • 9
  • 48
  • 101
0

Why can't you use the same class (let's say Bolt) for all of these? They look similar, they share the same properties, does their behavior change? If so, then just use a decorator based on the bolt type around an instance.

Tassos Bassoukos
  • 16,017
  • 2
  • 36
  • 40
  • The bolt's specifications (dimensions of the bolt's head) differ between types of bolts. boltSpec is a property of bolt. So I need a HexHead Bolt, a PanHeadBolt, a socketCapHeadBolt, etc. So I don't know what you are really asking, but I have things working using the discriminatorformula. – jeff Jan 12 '16 at 23:57