shx
shx

Reputation: 1138

Hibernate @ManyToOne mapping - automatic loading without @Id property set

How can I force Hibernate to load my main object with some other object from ManyToOne relation? That's the moment where some other value is set, other than @Id property.

Can you check my repo with maven project on github, HbnAddressDaoTest is a JUnit test class where I'm trying this behaviour

Address is the entity class I would like to persist to database but only have country code from Country. All rows in Country table are constants, so Country object shouldn't be inserted again, only countryId need to be written. Is there any automation mechanism in Hibernate for this or do I have to manually load Country in some service transactional method before Address persistence?

Upvotes: 0

Views: 432

Answers (1)

Arturo Volpe
Arturo Volpe

Reputation: 3627

No, it's not posible, java can't know when new Country("BE") are equal to countryDao.getByCode("BE"), because, there are not equals, one is managed by Hibernate and the other is managed by you.

You don't give the new Country("BE") to Hibernate, so it can not be the same, also, went you invoke the new Countru("BE"), the code is null, and the code of countryDao.getByCode("BE") is not null (it was created by your SQL script and now is managed by Hibernate).

You have two options:

  • Change your test to:

    Country country = countryDao.getByCode("BE");
    Address address = new Address();
    address.setCountry(country);
    addressDao.create(address);
    assertEquals(country.getCountryId(), addressDao.get(address.getAddressId()).getCountry().getCountryId());
    

    To test if the address is correctly persisted, or:

  • Create a CountryProvider like this:

    public class CountryProvider {
    
         @Autowired HbnCountryDao dao;
         Map<String, Country> map = new HashMap<String, Country>();
    
         public Country getByCode(String code) {
             if (map.contains(code)) return map.get(code);
             Country toRet = dao.getByCode(code);
             map.put(code, toRet);
             return toRet;
         }
    }
    

    Make all of your Country constructors private or protected, and only access the Country by the CountryProvider.

Upvotes: 1

Related Questions