문제

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();
    }

    .
    .
    .
}
도움이 되었습니까?

해결책

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.

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top