简体   繁体   中英

hibernate - how to persist all entities and subentities at once

Need help with some Hibernate issues.

1) Want to persist all entities and subentities from one object at once, running the create() method. Is it possible?

2) Having problems with join table. Nothing is persisting in it. I tried to put @ManyToMany mappings to Set collections in Person and Address classes. Never made it to work and to fill the PERSON_ADDRESS table in database.

I have two test methods which I try to run from my test case class. They are all at my git . Methods are testJoinTable() and testLoadEverything() . Please, take a look. Hibernate mappings are in classes from model package.

Address.java

@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {

    @ManyToOne(targetEntity = Country.class)
    @JoinColumn(name = "COUNTRY_ID", referencedColumnName = "COUNTRY_ID", insertable = true, nullable = true, unique = false, updatable = true)
    private Country country;

    @ManyToMany( mappedBy = "address" )
    private Set<Person> persons = new HashSet<Person>();

    @Column(name = "STREET", length = 100)
    private String street;

    @Column(name = "POST_CODE", length = 50)
    private String postCode;

    @Column(name = "ADDRESS_TYPE", length = 50)
    private String addressType;

    @Column(name = "ADDRESS_ID", nullable = false, precision = 20)
    @Id
    @SequenceGenerator(name = "AddressSeq", sequenceName = "ADDRESS_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AddressSeq")
    private Long addressId;

    @Column(name = "CITY", length = 100)
    private String city;

    @Column(name = "CREATED_ON", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdOn;

    @Column(name = "MODIFIED_ON")
    @Temporal(TemporalType.TIMESTAMP)
    private Date modifiedOn;

    @Column(name = "DISTRICT_NAME", length = 100)
    private String districtName;

    @OneToMany ( fetch = FetchType.LAZY, targetEntity = SomeId.class, mappedBy = "address" )
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.ALL})
    private Set<SomeId> someIds;

}

Person.java

@Entity
@Table(name = "PERSON")
public class Person implements Serializable {

    @Column(name = "PERSON_ID", nullable = false, precision = 20)
    @Id
    private Long personId;

    @ManyToMany
    @JoinTable(name="PERSON_ADDRESS", 
                joinColumns={@JoinColumn(name="PERSON_ID")}, 
                inverseJoinColumns={@JoinColumn(name="ADDRESS_ID")})
    private Set<Address> address = new HashSet<Address>();

    @Column(name = "CREATED_ON", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdOn;

    @Column(name = "MODIFIED_ON")
    @Temporal(TemporalType.TIMESTAMP)
    private Date modifiedOn;
}

Country.java

@Entity
@Table(name = "COUNTRY")
@NamedQuery(name = "findCountryByCode", query = "from Country where code like :code")
public class Country implements Serializable {

    @Column(name = "COUNTRY_ID", nullable = false, precision = 20)
    @Id
    @SequenceGenerator(name = "CountrySeq", sequenceName = "COUNTRY_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CountrySeq")
    private Long countryId;

    @OneToMany(targetEntity = Birth.class, mappedBy = "country")
    private Collection<Birth> birthCollection;

    @OneToMany(targetEntity = Address.class, mappedBy = "country")
    private Collection<Address> addressCollection;

    @Column(name = "CODE", nullable = false, length = 2)
    private String code;

    @Column(name = "CREATED_ON", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdOn;

    @Column(name = "MODIFIED_ON")
    @Temporal(TemporalType.TIMESTAMP)
    private Date modifiedOn;
}

SomeId.java

@Entity
@Table( name = "SOME_ID" )
public class SomeId {

    @Column( name = "SOME_ID_ID", unique = true, nullable = false, precision = 20, scale = 0 )
    @Id
    @SequenceGenerator( name = "SomeIdSeq", sequenceName = "SOME_ID_ID_SEQ", allocationSize = 1 )
    @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "SomeIdSeq" )
    private Long someIdId;

    @ManyToOne( optional = false, targetEntity = Address.class, fetch = FetchType.EAGER)
    @JoinColumn( name = "ADDRESS_ID", referencedColumnName = "ADDRESS_ID", insertable = true, nullable = true, unique = false, updatable = true )
    private Address address;

    @Column( name = "CREATED_ON", nullable = false )
    @Temporal( TemporalType.TIMESTAMP )
    private Date createdOn;

    @Column( name = "MODIFIED_ON" )
    @Temporal( TemporalType.TIMESTAMP )
    private Date modifiedOn;

    @Column( name = "SOME_ID", nullable = false, length = 100 )
    private String someId;
}

To easier get the point what am I trying to accomplish, I'll paste my test methods here:

@Test
public void testJoinTable() {
    addressDao.create( address1 );
    addressDao.create( address2 );
    Address address = addressDao.get( address2.getAddressId() );
    assertTrue("address2 don't have 3 persons as expected", address.getPersons().size() == 3);
    long numberOfRecordsInJoinTable = personAddressDao.count();
    assertTrue( "join table PERSON_ADDRESS is not used by Hibernate", numberOfRecordsInJoinTable > 0 );
}

@Test
public void testLoadEverything() {
    address1.setSomeIds( new HashSet<SomeId>() );
    address1.getSomeIds().add( someId1 );
    address1.getSomeIds().add( someId2 );
    addressDao.create( address1 );
    long numberOfRecordsInSomeIdTable = someIdDao.count();
    assertTrue("someIds are not persisted", numberOfRecordsInSomeIdTable > 0);
}

Looks like you need to specify the cascade options on the manytomany from Person > Address:

http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Cascading

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