Q:

Spring data jpa one-to-one optional shared primary key

I wouldn't think that my case is unusual, but maybe I'm missing something.  Here is the database setup:
Table: proposalitems
Columns:
PK_ProposalRevisionItemID int(10) UN AI PK 
FK_ProposalID int(10) UN 
FK_RevisionID varchar(2) 
ItemID int(10) UN 
ItemText text 
Delivery varchar(9) 
Qty smallint(5) UN 
PriceEach decimal(10,2) UN 
LikelihoodOfSale tinyint(3) UN 
FK_MfgTimeID int(10) UN

CREATE TABLE `proposalitems` (
  `PK_ProposalRevisionItemID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `FK_ProposalID` int(10) unsigned NOT NULL,
  `FK_RevisionID` varchar(2) NOT NULL,
  `ItemID` int(10) unsigned NOT NULL,
  `ItemText` text,
  `Delivery` varchar(9) DEFAULT 'Standard',
  `Qty` smallint(5) unsigned DEFAULT '1',
  `PriceEach` decimal(10,2) unsigned DEFAULT '0.00',
  `LikelihoodOfSale` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `FK_MfgTimeID` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`PK_ProposalRevisionItemID`),
  KEY `FK_MfgTime_idx` (`FK_MfgTimeID`),
  KEY `FK_ItemPropRevID_idx` (`FK_ProposalID`,`FK_RevisionID`),
  CONSTRAINT `FK_ItemPropRevID` FOREIGN KEY (`FK_ProposalID`, `FK_RevisionID`) REFERENCES `proposalrevisions` (`FK_ProposalID`, `FK_RevisionID`) ON DELETE CASCADE ON UPDATE NO ACTION,
  CONSTRAINT `FK_MfgTime` FOREIGN KEY (`FK_MfgTimeID`) REFERENCES `proposalitemmnfgtimes` (`PK_ItemMnfgTimeID`)
) ENGINE=InnoDB AUTO_INCREMENT=6161 DEFAULT CHARSET=utf8;

proposalitems is the parent table.
Table: proposalexpdelivery
Columns:
FK_ProposalRevisionItemID int(10) UN PK 
DeliveryTime tinyint(3) UN 
FK_DelUnitID int(10) UN 
FK_DeliveryClauseID int(10) UN

CREATE TABLE `proposalexpdelivery` (
  `FK_ProposalRevisionItemID` int(10) unsigned NOT NULL,
  `DeliveryTime` tinyint(3) unsigned NOT NULL DEFAULT '4',
  `FK_DelUnitID` int(10) unsigned DEFAULT NULL,
  `FK_DeliveryClauseID` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`FK_ProposalRevisionItemID`),
  KEY `FK_ExpDelUnitID` (`FK_DelUnitID`),
  KEY `FK_ExpDeliveryClauseID` (`FK_DeliveryClauseID`),
  CONSTRAINT `FK_ExpDelUnitID` FOREIGN KEY (`FK_DelUnitID`) REFERENCES `units` (`PK_UnitID`),
  CONSTRAINT `FK_ExpDeliveryClauseID` FOREIGN KEY (`FK_DeliveryClauseID`) REFERENCES `proposaldeliveryclause` (`PK_DeliveryClauseID`),
  CONSTRAINT `FK_expPropRevItemID` FOREIGN KEY (`FK_ProposalRevisionItemID`) REFERENCES `proposalitems` (`PK_ProposalRevisionItemID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

So basically I have a table of proposal items.  Each item may or may not have an expedited delivery.  If it does, the expedited delivery record is saved in the proposalexpdelivery table, using the same id as in the proposalitems table.  Most of the examples I saw have a set one to one relationship, where if one exists, the other must also exist.  In my case, there does not have to be an expedited delivery record for each item.
I only care about accessing the expedited delivery data from the proposal item.  There would not be a need to access the expedited delivery record and from that get the proposal item data.
Here is the class for ProposalItem:
@Entity
@Table(name="sales.proposalitems", uniqueConstraints=@UniqueConstraint(columnNames={"fk_proposalid","fk_revisionid","itemid"}))
public class ProposalItem implements Serializable {
    ...
    private int proposalRevisionItemID;
    ...
    private ProposalExpeditedDelivery expeditedDelivery;
    ...
    @Id
    @Column(name="pk_proposalrevisionitemid")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonView(View.SimpleProposalView.class)
    public int getProposalRevisionItemID() {
        return proposalRevisionItemID;
    }

    public void setProposalRevisionItemID(int proposalRevisionItemID) {
        this.proposalRevisionItemID = proposalRevisionItemID;
    }
    ...
//    @OneToOne(optional=true,cascade={CascadeType.PERSIST,CascadeType.REMOVE}, orphanRemoval=true, mappedBy="proposalItem", fetch=FetchType.LAZY)
//    @JoinColumn(name="pk_proposalrevisionitemid", referencedColumnName="fk_proposalrevisionitemid")
//    @OneToOne(cascade=CascadeType.ALL, mappedBy="proposalItem")
//    @Transient
//    @OneToOne(optional=true,cascade={CascadeType.ALL}, orphanRemoval=true, fetch=FetchType.LAZY)
//    @JoinColumn(name="pk_proposalrevisionitemid", referencedColumnName="fk_proposalrevisionitemid")
    public ProposalExpeditedDelivery getExpeditedDelivery() {
        return this.expeditedDelivery;
    }

    public void setExpeditedDelivery(ProposalExpeditedDelivery expeditedDelivery) {
        this.expeditedDelivery = expeditedDelivery;
    }
    ...
}

And for the expedited delivery class:
@Entity
@Table(name="sales.proposalexpdelivery")
public class ProposalExpeditedDelivery implements Serializable {
    ...
    private int proposalRevisionItemID;
    private ProposalItem proposalItem;
    ...
    @Id
    @JoinColumn(name="fk_proposalrevisionitemid")
    public int getProposalRevisionItemID() {
        return proposalRevisionItemID;
    }

    public void setProposalRevisionItemID(int proposalRevisionItemID) {
        this.proposalRevisionItemID = proposalRevisionItemID;
    }

    @OneToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="fk_proposalrevisionitemid")
    @MapsId
    public ProposalItem getProposalItem() {
        return proposalItem;
    }

    public void setProposalItem(ProposalItem proposalItem) {
        this.proposalItem = proposalItem;
    }
    ...
}

I have tried all kinds of different things.  I could successfully retrieve the expedited delivery data, but as soon as I wanted to update or add, it wouldn't work.  I would get a variety of errors depending on which annotations I had at the time.
I have a repository and service layer for proposal items.  I'm thinking that I don't need those for the expedited delivery if cascading is working properly, but maybe I'm wrong about that.
In my test, I've tried to set both the delivery in the item and the item in the delivery, and I've tried creating a repository for the delivery and then saving the delivery before saving the item, but nothing I have tried has worked.
I would love to see a clear example of which annotations to use and ideally how to set up a test to add and edit a delivery to an item, but I would be happy with just the correct annotations.
I am using Spring Boot, which is using Hibernate 5.2.12.
Also, I believe my database structure is set up correctly and efficiently (I am using MySQL), but if there is a better to achieve what I need, I am able to restructure the database if needed.
EDIT:
My code to test this has an existing ProposalItem object.  I then create a new ProposalExpeditedDelivery object and try to save the ProposalItem.
ProposalExpeditedDelivery ped = new ProposalExpeditedDelivery();
ped.setDeliveryTime(4);
ped.setDeliveryUnit(unit);
ped.setDeliveryClause(clause);
//ped.setProposalItem(proposalItem);
proposalItem.setExpeditedDelivery(ped);

//expeditedDeliveryRepository.save(ped);
proposalItemRepository.save(proposalItem);

Like this (and using egallardo's answer) I get the error:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing

If I uncomment the line so that it tries to save the ProposalExpeditedDelivery object first, I get the error:
attempted to assign id from null one-to-one property

If I uncomment both of the commented lines above, I get the error:
detached entity passed to persist

A:

Remove the extra JoinColumn, just think in terms of objects (not database keys):
@Entity
@Table(name="sales.proposalexpdelivery")
public class ProposalExpeditedDelivery implements Serializable {
    ...
    private ProposalItem proposalItem;
    ...

    @Id
    @GenericGenerator(name = "generator", strategy = "foreign",  parameters = @Parameter(name = "property", value = "proposalItem"))
    @GeneratedValue(generator = "generator")
    @JoinColumn(name="fk_proposalrevisionitemid", unique=true, nullable=false)
    public int getProposalRevisionItemID() {
        return proposalRevisionItemID;
    }

    @OneToOne(fetch=FetchType.LAZY)
    @PrimaryKeyJoinColumn
    public ProposalItem getProposalItem() {
        return proposalItem;
    }

    public void setProposalItem(ProposalItem proposalItem) {
        this.proposalItem = proposalItem;
    }
    ...
}

The parent entity should look like this:
@Entity
@Table(name="sales.proposalitems", uniqueConstraints=@UniqueConstraint(columnNames={"fk_proposalid","fk_revisionid","itemid"}))
public class ProposalItem implements Serializable {
    ...
    private int proposalRevisionItemID;
    ...
    private ProposalExpeditedDelivery expeditedDelivery;
    ...
    @Id
    @Column(name="pk_proposalrevisionitemid", unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonView(View.SimpleProposalView.class)
    public int getProposalRevisionItemID() {
        return proposalRevisionItemID;
    }

    public void setProposalRevisionItemID(int proposalRevisionItemID) {
        this.proposalRevisionItemID = proposalRevisionItemID;
    }
    ...
    @OneToOne(fetch = FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="proposalItem")
    public ProposalExpeditedDelivery getExpeditedDelivery() {
        return this.expeditedDelivery;
    }

    public void setExpeditedDelivery(ProposalExpeditedDelivery expeditedDelivery) {
        this.expeditedDelivery = expeditedDelivery;
    }
    ...
}

Test code:
retrieve proposalItem;

ProposalExpeditedDelivery ped = proposalItem.getExpeditedItem();
if(ped == null){
  ped = new ProposalExpeditedDelivery();
  ped.setProposalItem(proposalItem);
  proposalItem.setExpeditedItem(ped);
  expeditedDeliveryRepository.save(ped);
}

ped.setDeliveryTime(4);
ped.setDeliveryUnit(unit);
ped.setDeliveryClause(clause);

proposalItemRepository.save(proposalItem);

On the service layer for Proposal Items, here is the update code:
@Override
public ProposalItem update(ProposalItem entity) throws EntityNotFoundException {
    ProposalItem ent = null;
    try {
        ent = repository.findById(entity.getProposalRevisionItemID()).get();
    } catch (Exception ex) {
        LOGGER.error(ex.getMessage());
        throw new EntityNotFoundException();
    }
    if (ent == null) {
        throw new EntityNotFoundException();
    }
    // get the expedited delivery object from the existing database entry
    ProposalExpeditedDelivery ped = ent.getExpeditedDelivery();
    // if the existing database entry is null but the update client object does contain a ProposalExpeditedDelivery object
    if (ped==null && entity.getExpeditedDelivery()!=null) {
        entity.getExpeditedDelivery().setProposalItem(ent);
        ent.setExpeditedDelivery(entity.getExpeditedDelivery());
        expeditedDeliveryRepository.save(ent.getExpeditedDelivery());
    }
    // if the existing database entry has an expedited delivery object, but the client object does not
    else if (ped!=null && entity.getExpeditedDelivery()==null) {
        expeditedDeliveryRepository.delete(ped);
    } 
    // if both the existing database entry and the client entry have an expedited delivery object, but they are not equal
    else if (ped!=null && !ent.getExpeditedDelivery().equals(entity.getExpeditedDelivery())) {
        ped.setDeliveryTime(entity.getExpeditedDelivery().getDeliveryTime());
        ped.setDeliveryUnit(entity.getExpeditedDelivery().getDeliveryUnit());
        ped.setDeliveryClause(entity.getExpeditedDelivery().getDeliveryClause());
        expeditedDeliveryRepository.save(ent.getExpeditedDelivery());
    }
    entity = setupForUpdate(entity);
    if (entity.getExpeditedDelivery()!=null) {
        entity.setExpeditedDelivery(ent.getExpeditedDelivery());
    }
    return repository.save(entity);
}

The logic for update is basically:

Receive client object
Load existing object from DB
Change/update object properties
Save changes

