简体   繁体   中英

Multiple @Embedded fields of same type are always null after persisting

I've implemented the following hierachy:

Abstract Superclass: ConnectionTechnologyDetails
Subclass: AS2
Embeddable: AS2Details

The Subclass AS2 has additional attributes and methods in comparsion to it's superclass. The additional attributes are @Embedded types of AS2Details.

When I'm saving the AS2 subclass instance to it's repository, the @Embedded fields seem to get lost. When I'm priniting the saved instance all @Embedded fields are null . I don't know why because printing before saving to repository results in filled @Embedded fields.

Outcome after persist

  "connectionTechnologyDetails": {
        "id": 2,
        "connectionTechnologyName": "AS2",
        "senderReceiverIds": {
            "senderIDOutbound": "HLCU",
            "receiverIDOutbound": "BASF",
            "senderIdInbound": "BASF",
            "receiverIdInbound": "HLCU"
        },
        "companyTestDetails": null,
        "companyProdDetails": null,
        "hlagTestDetails": null,
        "hlagProdDetails": null,
        "testString": "testStringShowsUp"
    }

ConnectionTechnologyDetails

import javax.persistence.*;
import javax.validation.constraints.NotNull;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "TECH_TYPE")
public abstract class ConnectionTechnologyDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne
@PrimaryKeyJoinColumn
private Connection connection;

@NotNull
private ConnectionTechnologyName connectionTechnologyName;

@Embedded
private SenderReceiverIds senderReceiverIds;

public ConnectionTechnologyDetails(ConnectionTechnologyName connectionTechnologyName, SenderReceiverIds senderReceiverIds) {
    this.connectionTechnologyName = connectionTechnologyName;
    this.senderReceiverIds = senderReceiverIds;
}

public ConnectionTechnologyDetails() {

}

public ConnectionTechnologyName getConnectionTechnologyName() {
    return connectionTechnologyName;
}

public void setConnectionTechnologyName(ConnectionTechnologyName connectionTechnologyName) {
    this.connectionTechnologyName = connectionTechnologyName;
}

public SenderReceiverIds getSenderReceiverIds() {
    return senderReceiverIds;
}

public void setSenderReceiverIds(SenderReceiverIds senderReceiverIds) {
    this.senderReceiverIds = senderReceiverIds;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public enum ConnectionTechnologyName {
    SMTP,
    AS2,
    UNSECURE_FTP,
    SECURE_FTP,
    FTP_SECURE
}

@Override
public String toString() {
    return "ConnectionTechnologyDetails: Name=" +getConnectionTechnologyName().name()
            + " SenderReceiverIds=" + getSenderReceiverIds();
}

}

AS2

(Even tried to hardcode the first @Embedded field. But even this doesn't work.)

import javax.persistence.*;
import javax.validation.constraints.NotNull;

@Entity(name = "AS2")
@Table(name = "AS2")
@DiscriminatorValue("AS2")
public class AS2 extends ConnectionTechnologyDetails {
    @NotNull
    @Embedded
    private AS2Details companyTestDetails = new AS2Details("192.1.168.1",
            "ctest", "localhost:8080", "ctest2", "90", "111.00.5.4",
            "scharpe", "+9+992++*9*+", "AS3");
    @NotNull
    @Embedded
    private AS2Details companyProdDetails;
    @NotNull
    @Embedded
    private AS2Details hlagTestDetails;
    @NotNull
    @Embedded
    private AS2Details hlagProdDetails;
    private String testString;

    public AS2(ConnectionTechnologyName connectionTechnologyName, SenderReceiverIds senderReceiverIds,
               AS2Details companyTestDetails, AS2Details companyProdDetails, AS2Details hlagTestDetails,
               AS2Details hlagProdDetails) {
        super(connectionTechnologyName, senderReceiverIds);
        System.err.println("ERROR---- companyTestDetails = " + companyTestDetails);
        this.companyTestDetails = companyTestDetails;
        this.companyProdDetails = companyProdDetails;
        this.hlagTestDetails = hlagTestDetails;
        this.hlagProdDetails = hlagProdDetails;
        testString = "testStringShowsUp";
    }

    public AS2() {
        super();
    }


    public void setHlagProdDetails(AS2Details hlagProdDetails) {
        this.hlagProdDetails = hlagProdDetails;
    }

    @Override
    public String toString() {
        return "AS2 Technology: Company: " + getCompanyTestDetails() + " / " + getCompanyProdDetails() + " HLAG: " +
                getHlagTestDetails() + " " + getHlagTestDetails() + getTestString();
    }

    public AS2Details getCompanyTestDetails() {
        return companyTestDetails;
    }

    public void setCompanyTestDetails(AS2Details companyTestDetails) {
        this.companyTestDetails = companyTestDetails;
    }

    public AS2Details getCompanyProdDetails() {
        return companyProdDetails;
    }

    public void setCompanyProdDetails(AS2Details companyProdDetails) {
        this.companyProdDetails = companyProdDetails;
    }

    public AS2Details getHlagTestDetails() {
        return hlagTestDetails;
    }

    public void setHlagTestDetails(AS2Details hlagTestDetails) {
        this.hlagTestDetails = hlagTestDetails;
    }

    public AS2Details getHlagProdDetails() {
        return hlagProdDetails;
    }

    public String getTestString() {
        return testString;
    }

    public void setTestString(String testString) {
        this.testString = testString;
    }
}

AS2Details

import javax.persistence.Column;
import javax.persistence.Embeddable;

public class AS2Details {
    @Column(name = "ip1", insertable = false, updatable = false)
    private String ip1;
    @Column(name = "as1id1", insertable = false, updatable = false)
    private String AS2ID1;
    @Column(name = "url", insertable = false, updatable = false)
    private String url;
    @Column(name = "as2id2", insertable = false, updatable = false)
    private String AS2ID2;
    @Column(name = "port", insertable = false, updatable = false)
    private String port;
    @Column(name = "ip2", insertable = false, updatable = false)
    private String ip2;
    @Column(name = "as2sofware", insertable = false, updatable = false)
    private String AS2Software;
    @Column(name = "userid", insertable = false, updatable = false)
    private String userId;
    @Column(name = "password", insertable = false, updatable = false)
    private String password;

    public AS2Details(String ip1, String AS2ID1, String url, String AS2ID2,
                      String port, String ip2, String userId, String password, String AS2Software) {
        this.ip1 = ip1;
        this.AS2ID1 = AS2ID1;
        this.url = url;
        this.AS2ID2 = AS2ID2;
        this.port = port;
        this.ip2 = ip2;
        this.userId = userId;
        this.password = password;
        this.AS2Software = AS2Software;
    }

    public AS2Details() {

    }

    public String getIp1() {
        return ip1;
    }

    public void setIp1(String ip1) {
        this.ip1 = ip1;
    }

    public String getAS2ID1() {
        return AS2ID1;
    }

    public void setAS2ID1(String AS2ID1) {
        this.AS2ID1 = AS2ID1;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getAS2ID2() {
        return AS2ID2;
    }

    public void setAS2ID2(String AS2ID2) {
        this.AS2ID2 = AS2ID2;
    }

    public String getPort() {
        return port;
    }

    public void setPort(String port) {
        this.port = port;
    }

    public String getIp2() {
        return ip2;
    }

    public void setIp2(String ip2) {
        this.ip2 = ip2;
    }

    public String getAS2Software() {
        return AS2Software;
    }

    public void setAS2Software(String AS2Software) {
        this.AS2Software = AS2Software;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "AS2 Details: " + getAS2ID1() + getAS2ID2() + getIp1() + getIp2() + getPassword();
    }
}

Data creation in CommandLineRunner

    AS2Details companyTestDetails = new AS2Details("192.1.168.1",
            "ctest", "localhost:8080", "ctest2", "90", "111.00.5.4",
            "scharpe", "+9+992++*9*+", "AS3");
    AS2Details companyProdDetails = new AS2Details("192.1.168.1",
            "cp", "localhost:8080", "cp", "90", "111.00.5.4",
            "scharpe", "+9+992++*9*+", "AS3");
    AS2Details hlagTestDetails = new AS2Details("192.1.168.1",
            "htest1", "localhost:8080", "htest2", "90", "111.00.5.4",
            "scharpe", "+9+992++*9*+", "AS3");
    AS2Details hlagProdDetails = new AS2Details("192.1.168.1",
            "hp1", "localhost:8080", "hp2", "90", "111.00.5.4",
            "scharpe", "+9+992++*9*+", "AS3");

    AS2 as2 = connectionTechnologyDetailsRepository.save(new AS2(ConnectionTechnologyDetails
            .ConnectionTechnologyName.AS2, senderReceiverIds,
            companyTestDetails, companyProdDetails, hlagTestDetails, new AS2Details()));

    logger.info("CommandLineRunner: connectionTechnology AS2: " + as2.toString());
    Connection userAs2Connection = new Connection(userRepository.findByUsername("userman").get(),
            contactDetailsRepository.findFirstByOrderByIdAsc(),
            BusinessCase.CONSIGNEE,
            as2);
    connectionRepository.save(userAs2Connection);

Why are the embedded fields null and the fields of the superclass filled? When I'm printing the fields from the constructor in the subclass, the data is correctly there. But it's not saved from the constructor to the embedded fields.

Solved by myself.

If you map multiple @Embedded fields of the same type (AS2Details), you have to overwrite their attributes. Otherwise you have a name conflict in your table because multiple columns would have the same name. For example in this case you would have column url and column url in the same single table .

Therefore I added an onverride annotation to each embedded field in AS2 class. For example the first field:

    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name="ip1", column=@Column(name="companyTestDetails_ip1")),
        @AttributeOverride(name="AS2ID1", column=@Column(name="companyTestDetails_as2id1")),
        @AttributeOverride(name="url", column=@Column(name="companyTestDetails_url")),
        @AttributeOverride(name="AS2ID2", column=@Column(name="companyTestDetails_as2id2")),
        @AttributeOverride(name="port", column=@Column(name="companyTestDetails_port")),
        @AttributeOverride(name="ip2", column=@Column(name="companyTestDetails_ip2")),
        @AttributeOverride(name="userId", column=@Column(name="companyTestDetails_userId")),
        @AttributeOverride(name="password", column=@Column(name="companyTestDetails_password")),
        @AttributeOverride(name="AS2Software", column=@Column(name="companyTestDetails_as2software"))
})
private AS2Details companyTestDetails;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM