I have an entity with child one-to-one entity, that could be skipped. I decided to use @MapsId and use same identifier for both entities. But when CrudRepository fires "save" operation, it calls hibernate's method "merge" and saving crushes.
{code:java} public class MapsIdTestCase extends BaseCoreFunctionalTestCase {
@Override protected Class[] getAnnotatedClasses() { return new Class[]{ Foo.class, Bar.class }; }
// If you use *.hbm.xml mappings, instead of annotations, add the mappings here. @Override protected String[] getMappings() { return new String[]{}; }
// If those mappings reside somewhere other than resources/org/hibernate/test, change this. @Override protected String getBaseForMappings() { return "org/hibernate/test/"; }
// Add in any settings that are specific to your test. See resources/hibernate.properties for the defaults. @Override protected void configure(Configuration configuration) { super.configure(configuration);
configuration.setProperty(AvailableSettings.SHOW_SQL, Boolean.TRUE.toString()); configuration.setProperty(AvailableSettings.FORMAT_SQL, Boolean.TRUE.toString()); configuration.setProperty("hibernate.temp.use_jdbc_metadata_defaults", Boolean.FALSE.toString()); configuration.setProperty("cache.provider_class", "org.hibernate.cache.internal.NoCachingRegionFactory"); configuration.setProperty(Environment.DIALECT, "org.hibernate.dialect.Oracle10gDialect"); configuration.setProperty(Environment.ORDER_UPDATES, Boolean.TRUE.toString()); configuration.setProperty(Environment.AUTOCOMMIT, Boolean.FALSE.toString()); configuration.setProperty(Environment.USE_STREAMS_FOR_BINARY, Boolean.TRUE.toString()); configuration.setProperty(Environment.USE_SCROLLABLE_RESULTSET, Boolean.TRUE.toString()); configuration.setProperty(Environment.USE_NEW_ID_GENERATOR_MAPPINGS, Boolean.TRUE.toString());
//configuration.setProperty( AvailableSettings.GENERATE_STATISTICS, "true" ); }
// Add your tests, using standard JUnit. @Test public void mainTest() throws Exception {
final Long fooId = 500L;
doInHibernate(this::sessionFactory, session -> {
Foo foo = new Foo(); foo.setId(fooId); foo.setName("Foo1"); session.save(foo); });
doInHibernate(this::sessionFactory, session -> {
Foo foo = session.find(Foo.class, fooId);
Bar bar = foo.getBar(); if (bar == null) { bar = new Bar(foo); foo.setBar(bar); } bar.setName("Bar2"); session.merge(foo); });
doInHibernate(this::sessionFactory, session -> { Foo foo = session.find(Foo.class, fooId); assertNotNull(foo.getBar()); }); }
@Entity @Table(name = "TEST_FOO") public static class Foo {
private Long id; private String name; private Bar bar;
@Id @Column(name = "ID") public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@Column(name = "name") public String getName() { return name; }
public void setName(String name) { this.name = name; }
@OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "foo_id") public Bar getBar() { return bar; }
public void setBar(Bar bar) { this.bar = bar; } }
@Entity @Table(name = "TEST_BAR") public static class Bar {
private Long id; private Foo foo; private String name;
public Bar() { }
Bar(Foo foo) { this.foo = foo; }
@Id @GeneratedValue(generator = "foreign") @GenericGenerator(name = "foreign", strategy = "foreign", parameters = { @org.hibernate.annotations.Parameter(name = "property", value = "foo") }) @Column(name = "foo_id") public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@OneToOne(mappedBy = "bar") @MapsId("foo_id") public Foo getFoo() { return foo; }
public void setFoo(Foo foo) { this.foo = foo; }
@Column(name = "name") public String getName() { return name; }
public void setName(String name) { this.name = name; } } } {code} |
|