0

I have a Stock entity which has 2 child entities, stock can only be vehicle or property, not both, stock is defined as follows:

@RooJavaBean
@RooToString
@RooJpaActiveRecord
public class Stock {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Version
    @Column(name = "version")
    private Integer version;

    ...

    @OneToOne(mappedBy = "stock", cascade = CascadeType.ALL)
    private StockProperty property;
    private Boolean isProperty;

    @OneToOne(mappedBy = "stock", cascade = CascadeType.ALL)
    private StockVehicle vehicle;
    private Boolean isVehicle;

    ....

}

And then the child entity StockProperty:

@RooJavaBean
@RooToString
@RooJpaActiveRecord
public class StockProperty {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Version
    @Column(name = "version")
    private Integer version;

    ....

    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL)
    private Stock stock;

    ... more fields containing property details

}

StockVehicle follows exactly the same pattern:

@RooJavaBean
@RooToString
@RooJpaActiveRecord
public class StockVehicle {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Version
    @Column(name = "version")
    private Integer version;

    ....

    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL)
    private Stock stock;

    ... more fields containing vehicle details

}

When trying to link the two, it's always null in the database:

Stock stock = new Stock();
stock.setProperty(new StockProperty());
stock.getProperty().persist();
stock.persist();

Or the other way around, it's still null on both sides:

Stock stock = new Stock();

... fill in stock details

StockProperty property = new StockProperty();
property.setStock(stock);
... fill in property details

stock.setProperty(property);
stock.persist();

property.persist();

I'm not seeing any errors in the logs, but the linking just never happens:

Stock's propery fields are all null:

enter image description here

StockProperty's stock fields are all null:

enter image description here

I'm trying to implement a cascade delete, so when I'm deleting Stock, it must delete StockProperty and if possible, the other way around as well, otherwise I would have made it a one-directional reference.

Update SQL as requested:

Hibernate: insert into stock (account, company, created, full_description, ..., is_property, is_vehicle, modified, version) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Hibernate: select last_insert_id()

Hibernate: insert into stock_property (created, modified, ... , version) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Hibernate: select last_insert_id()

I don't see the property field in the stock insert sql, neither do I see the stock field in the insert sql for stock_property.

Jan Vladimir Mostert
  • 12,380
  • 15
  • 80
  • 137
  • 1
    I hope if it could help you http://stackoverflow.com/questions/9850566/null-foreign-key-in-manytoone-relation-using-hibernate-4-1-1-annotations – Make Jun 10 '15 at 05:55
  • Nope, updated my question with an example where I'm trying to manually link it both ways without success. – Jan Vladimir Mostert Jun 10 '15 at 06:12
  • 1
    I don't know how `SpringRoo` works but seems very invasive. Any way I would expect to see `@Entity`annotations on all classes that are candidates for persistence. Using logging/debugger you should be able to see the `SQL` for inserts. Can you paste that ? – Shahzeb Jun 10 '15 at 06:19
  • 1
    Is this logic inside on a non-static method annotated with @Transactional? – jmvivo Jun 10 '15 at 06:21
  • @Shahzeb, I've updated with the SQL, I don't see either in the insert statements, interesting ... – Jan Vladimir Mostert Jun 10 '15 at 06:29
  • @jmvivo, that's correct, they are in a non-static method with (@)Transactional on top. That's the first thing I've checked :-) – Jan Vladimir Mostert Jun 10 '15 at 06:30
  • 1
    Try to remove `@PrimaryKeyJoinColumn` annotation: I think you don't need it. – jmvivo Jun 10 '15 at 06:33
  • That does make a difference, the stock_property table now has the stock id in it, but stock still doesn't have the stock_property id in it. Do I need the id in both? – Jan Vladimir Mostert Jun 10 '15 at 06:47
  • How do I make the cascade delete work? Deleting the Stock complaints about `Cannot delete or update a parent row: a foreign key constraint fails` – Jan Vladimir Mostert Jun 10 '15 at 06:53
  • Jan, this doubt is related to JPA, I suggest you read a good JPA guide. – eruiz Jun 10 '15 at 10:24

1 Answers1

1

Try this on StockProperty:

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "idStock", nullable = false)
private Stock stock;

And this on Stock:

@OneToOne(mappedBy="stock")
private StockProperty stockProperty;
Jean Cedron
  • 702
  • 3
  • 14
  • I've dropped my schema and let hibernate create a new schema, it's working now, except for delete. Hibernate adds a foreign key constraint between the two tables, now if I want to delete a row in either of them, it fails due to the foreign key constraint. – Jan Vladimir Mostert Jun 10 '15 at 18:17
  • Removing @JoinColumn removes the strict foreign-key constraint that disallows me to delete either, I can now delete the StockProperty first, then Stock and it works. – Jan Vladimir Mostert Jun 10 '15 at 18:58