2014-05-07 70 views
0

我有2个实体 - 媒体和关键字与一对多的关系。虽然我标记为Lazy Madia的抓取仍然获取所有关键字。懒惰加载一对多不工作

我使用弹簧3.2休眠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(); 
    } 

    . 
    . 
    . 
} 
+3

延迟加载是OneToMany的默认获取策略,无需手动指定。这就是说,它被拿来如何?在一个巨大的联接查询中或在几个查询中?打开SQL日志记录来查看实际情况。 – Gimby

回答

1

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

关键字没有被抓取,它们仍然在创建它们的持久性上下文中。

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

+0

冲洗和清除的伎俩。谢谢 – special0ne

0

FetchType.LAZY仅仅是一个暗示,持久性提供,它不是一个设置,可以依靠。只要认为合适,持久性提供者就可以自由地加载属性。

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