Question

I have 2 entities - Media and Keyword with one to many relationship. I though I marked the fetch to Lazy Madia is still fetching all the keywords.

I am using spring 3.2 Hibernate 4.3.4

Media Entity:

@Entity
public class Media {
@Id
    @NotNull
    @Column(name = "mediaid")
    private String mediaId;

    @NotNull
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "media", fetch = FetchType.LAZY)
    private List<Keyword> keywords;

    public List<Keyword> getKeywords() {
        return keywords;
    }

    public void setKeywords(List<Keyword> keywords) {
        if ( this.keywords!=null && this.keywords.size()>0 )
            this.keywords.addAll(keywords);
        else
            this.keywords = keywords;

        for (Keyword keyword : keywords) {
            keyword.setMedia(this);
        }
    }
}

Keyword Entity:

@Entity(name = "keywords")
public class Keyword {

    @Id
    @NotNull
    @Column(unique = true)
    private String idKey;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "idmedia")
    private Media media;

    public Media getMedia() {
        return media;
    }

    public void setMedia(Media media) {
        this.media = media;

        if (idKey == null || idKey.isEmpty())
            setIdKey(this.media.getMediaId());
        else
            setIdKey(this.media.getMediaId() + "_" + idKey);

        if (!media.containsKeyword(this))
            media.getKeywords().add(this);
    }
}

I can see the entities being fetch in the show_sql output but also this test fails

@WebAppConfiguration
@ContextConfiguration(classes = {PersistenceConfig.class})
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class MediasRepositoryTest extends AbstractTransactionalTestNGSpringContextTests {

    @Autowired
    MediasRepository mediasRepository;

    @PersistenceContext
    EntityManager manager;

    public void thatMediaLazyLoadsKeywords() throws Exception {
        PersistenceUnitUtil unitUtil = manager.getEntityManagerFactory().getPersistenceUnitUtil();

        Media media = DomainFixtures.createMedia();
        Media savedMedia = mediasRepository.save(media);
        Media retrievedMedia = mediasRepository.findOne(savedMedia.getMediaId());

        assertNotNull(retrievedMedia);
        assertFalse(unitUtil.isLoaded(retrievedMedia, "keywords"));
    }
}

Configuration:

@EnableTransactionManagement
public class PersistenceConfig {
    static Logger logger = LoggerFactory.getLogger(PersistenceConfig.class);
    @Autowired
    private Environment env;

//    @Value("${init-db:false}")
    private String initDatabase = "false";

    @Bean
    public DataSource dataSource()
    {
        logger.info("Starting dataSource");
        BasicDataSource dataSource = new BasicDataSource();
        logger.info("jdbc.driverClassName"+ env.getProperty("jdbc.driverClassName"));
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        logger.info("End dataSource");
        return dataSource;
    }

    @Bean
    public EntityManagerFactory entityManagerFactory() throws SQLException
    {
        logger.info("Starting entityManagerFactory");

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(Boolean.TRUE);

        vendorAdapter.setShowSql(Boolean.parseBoolean(env.getProperty("hibernate.show_sql")));
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan("....");
        factory.setDataSource(dataSource());

        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        jpaProperties.put("hibernate.enable_lazy_load_no_trans", true);
        jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
        factory.setJpaProperties(jpaProperties);
        factory.afterPropertiesSet();
        logger.info("End entityManagerFactory");
        return factory.getObject();
    }

    .
    .
    .
}
Was it helpful?

Solution

You test is running in the context of a single transaction.

The Keywords are not being fetched, they're still in the persistence context from when you created them.

Try adding a manager.clear() after your save method call.

OTHER TIPS

FetchType.LAZY is just a hint to the persistence provider, it is not a setting you can rely on. The persistence provider is free to load the attributes whenever it sees fit.

Thus you cannot reliably test whether lazy loading works as expected.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top