懒惰加载一对多不起作用

时间:2014-05-07 11:14:06

标签: java spring hibernate lazy-loading

我有2个实体 - 具有一对多关系的媒体和关键字。我虽然标记了对Lazy Madia的提取仍然取得所有关键字。

我使用的是Spring 3.2 Hibernate 4.3.4

媒体实体:

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

关键字实体:

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

我可以在show_sql输出中看到实体被提取,但是这个测试也失败了

@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"));
    }
}

配置:

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

    .
    .
    .
}

2 个答案:

答案 0 :(得分:1)

您的测试是在单个事务的上下文中运行。

关键字未被提取,它们仍然处于创建它们时的持久性上下文中。

尝试在保存方法调用后添加manager.clear()。

答案 1 :(得分:0)

FetchType.LAZY只是对持久性提供程序的提示,它不是您可以信赖的设置。持久性提供程序可以随时加载属性。

因此,您无法可靠地测试延迟加载是否按预期工作。