简体   繁体   中英

How to create two entities and relate them

First of all, apologize for the grammatical errors that you can make. My English is not very good.

I'm trying to create dinamically an Entity and relathion with other Entity.

The idea is send a json file and get some properties to create that Entity, later associate that entity with the other. However, I can't because throw Exception like:

attempted to assign id from null one-to-one property

So, here in my SchemeService I try to create both entities:

protected Scheme createScheme(final String creatorId, final String name, final String description, final InputStream inputStream) { 

    DeserializeJSONFile desJsonFile = new DeserializeJSONFile();
    desJsonFile.init(inputStream);

    TableEntity table = new TableEntity();
    table.setCreator(creatorId);
    table.setProperties(desJsonFile.getProperties().toString());
    table.setGeometry(desJsonFile.getGeometry().toString());
    createTable(table);

    Scheme scheme = new Scheme();
    scheme.setCreator(creatorId);
    scheme.setName(name);
    scheme.setDescription(description);
    scheme.setTable(table);
    createScheme(scheme);
    return scheme;
}

private void createTable(final TableEntity table) {
    tableDao.create(table);
}

protected void createScheme(final Scheme scheme) {
    schemeDao.create(scheme);
}

Here is my TableEntity:

public class TableEntity extends BaseEntityActivable implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SCHEME_SEQ_GEN")
    @SequenceGenerator(name = "SCHEME_SEQ_GEN", sequenceName = "test_seq_table", allocationSize = 1)
    @Column(name = "table_id")
    private Long tableId;

    @Type(type= "jsonb")
    @Column(name = "properties", columnDefinition = "json")
    private String properties;

    @Type(type= "jsonb")
    @Column(name = "geometry", columnDefinition = "json")
    private String geometry;

    @OneToOne
    @MapsId
    private Scheme scheme;
}

Here is my SchemeEntity:

public class Scheme extends BaseEntityActivable implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SCHEME_SEQ_GEN")
    @SequenceGenerator(name = "SCHEME_SEQ_GEN", sequenceName = "test_seq_scheme", allocationSize = 1)
    @Column(name = "scheme_id")
    private Long schemeId;

    @Column(name = "name", nullable = false)
    @NotEmpty(message = AxisMapsErrorConstants.NAME_CANT_BE_EMPTY)
    private String name;

    @Column(name = "description")
    private String description;

    @OneToOne(mappedBy = "scheme", cascade = CascadeType.ALL)
    @JoinColumn(name = "scheme_id", referencedColumnName = "table_id", foreignKey = @ForeignKey(name = "fk_scheme_table_1"))
    private TableEntity table;

}

Here is my sql:

create sequence test_seq_table start 1 increment 1;
create sequence test_seq_scheme start 1 increment 1;

create table maps_table (
    table_id int8 not null,
    created_at timestamp not null,
    created_by varchar(255),
    updated_at timestamp,
    updated_by varchar(255),
    is_active boolean not null,
    properties jsonb not null,
    geometry jsonb not null,
    primary key (table_id)
);


create table maps_scheme (
    scheme_id int8 not null,
    created_at timestamp not null,
    created_by varchar(255),
    updated_at timestamp,
    updated_by varchar(255),
    is_active boolean not null,
    description varchar(255),
    name varchar(255) not null,
    table_id int8 not null,
    primary key (scheme_id)
);

    alter table maps_scheme 
       add constraint fk_scheme_table_1 
       foreign key (scheme_id) 
       references maps_table;

since you are using @mapsId this means you are using the same identifier in your relation with scheme, which means first the scheme should not be nullable and it should be available as managed entity each time your object is flushed, which also means that you can do the persistence only from one side of the relation since the id of scheme should be available when persisting your entity.

I am not sure if you really need @mapsId here, since you already have a bidirectional relation which means anyway you will be able to access both sides of your entity.

I would suggest to remove @mapsId here.

Thanks everyone for helping me.

This is my solution.

Scheme:

public class Scheme extends BaseEntityActivable implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SCHEME_SEQ_GEN")
    @SequenceGenerator(name = "SCHEME_SEQ_GEN", sequenceName = "aguas_seq_scheme", allocationSize = 1)
    @Column(name = "scheme_id")
    private Long schemeId;

    @Column(name = "name", nullable = false)
    @NotEmpty(message = AxisMapsErrorConstants.NAME_CANT_BE_EMPTY)
    private String name;

    @Column(name = "description")
    private String description;

    @OneToOne(cascade= { CascadeType.ALL }, fetch = FetchType.LAZY)
    @JoinColumn(name="table_id")
    private TableEntity table;

}

TableEntity:

public class TableEntity extends BaseEntityActivable implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SCHEME_SEQ_GEN")
    @SequenceGenerator(name = "SCHEME_SEQ_GEN", sequenceName = "aguas_seq_table", allocationSize = 1)
    @Column(name = "table_id")
    private Long tableId;


    @Type(type= "jsonb")
    @Column(name = "properties", columnDefinition = "json")
    private String properties;

    @Type(type= "jsonb")
    @Column(name = "geometry", columnDefinition = "json")
    private String geometry;

    @OneToOne(mappedBy= "table")
    private Scheme scheme;
}

SQL:

create sequence aguas_seq_table start 1 increment 1;
create sequence aguas_seq_scheme start 1 increment 1;

create table maps_table (
    table_id int8 not null,
    created_at timestamp not null,
    created_by varchar(255),
    updated_at timestamp,
    updated_by varchar(255),
    is_active boolean not null,
    properties jsonb not null,
    geometry jsonb not null,
    primary key (table_id)
);


create table maps_scheme (
    scheme_id int8 not null,
    created_at timestamp not null,
    created_by varchar(255),
    updated_at timestamp,
    updated_by varchar(255),
    is_active boolean not null,
    description varchar(255),
    name varchar(255) not null,
    table_id int8 not null,
    primary key (scheme_id)
);

SchemeService to create scheme and table:

protected Scheme createScheme(final String creatorId, final String name, final String description, final InputStream inputStream) { 

    DeserializeJSONFile desJsonFile = new DeserializeJSONFile();
    desJsonFile.init(inputStream);

    TableEntity table = new TableEntity();
    table.setCreator(creatorId);
    table.setGeometry(desJsonFile.loadGeometries().toString());
    table.setProperties(desJsonFile.loadProperties().toString());
    createTable(table);

    Scheme scheme = new Scheme();
    scheme.setCreator(creatorId);
    scheme.setName(name);
    scheme.setDescription(description);
    scheme.setTable(table);
    createScheme(scheme);
    return scheme;
}

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