浏览 1296 次
该帖已经被评为隐藏帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-08-02
最后修改:2009-08-04
我在做一个相册,每个相册中可能有n张照片。目前相册与照片也配置成了双向一对多的关系。但我一直担心会出性能问题。 因为我发现好像用hibernate3的JPA配置里面,无法将一的一端设为“inverse”。所以如果添加相片,必须这样: photo.setAlbum(album); album.getPhotos().put(photo); albumManager.save(album); 这样每添加一张照片,就要获取一遍该相册中的所有相片! 有没有更好的办法? 比如将相片和相册设置成单向多对一? 或者干脆不配置关联,直接用程序逻辑控制关联?(我以前都是这么做的,但现在发现ORM的精髓就是关联,不配置关联实在可惜) 或者用大缓存解决这种问题?(总感觉不太合适,而且我们现在没有钱购买很贵的机器,如果非要这样的话,我觉得hibernate在这一点设计的也太烂了吧?) 刚还看了下面这篇帖子,跟我问的问题差不多,但几乎没有人能给予一个很肯定并且很有说服的答复。 http://www.iteye.com/topic/59707?page=1 恳请各位热心的大侠给予答复,谢谢! ===================================================================== 该问题已经解决,发现原来双向一对多的关联关系下,关联的双方都可以作为关系的主控端。所以使用的时候可以灵活运用。该问题自然迎刃而解! 附上测试代码,在Junit下测试通过: public void testAddAndRemoveAlbum2() throws Exception { Album album = new Album(); //album = (Album) populate(album); album.setName("iiiiiiiii"); album.setOwnerDisplayName("ssssssssss"); album.setOwnerId(new Long(-10)); Photo photo = new Photo(); photo.setCover(Boolean.FALSE); photo.setOwnerId(new Long(8)); photo.setPhotoPostfix(".jpg"); photo.setTitle("xxxxxxxxxxxxxxxxxxxxxx"); photo.setAlbum(album); album.getPhotos().add(photo); album = albumManager.addAlbum(album); assertNotNull(album.getId()); assertEquals("iiiiiiiii",album.getName()); assertEquals(1,album.getPhotos().size()); photo = album.getPhotos().iterator().next(); assertEquals(".jpg",photo.getPhotoPostfix()); assertEquals("iiiiiiiii",photo.getAlbum().getName()); long photoId = photo.getId(); //Photo photo = photoManager.get(-2L); //album = albumManager.updateAlbum(album); log.debug("removing photo..."); /** * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Hibernate之deleted object would be re-saved by cascade 异常的解决 * 解决关联关系后,再删除 : * * 还有其他几种解决方案: * 1) 删除Set方的cascade——将Photo类中对album的cascade属性删掉。 * 2) */ album.removePhoto(photo); photo.setAlbum(null); albumManager.removePhoto(photoId); try { photo = albumManager.getPhoto(photoId); fail("Photo found in database"); } catch (DataAccessException e) { log.debug("Expected exception: " + e.getMessage()); assertNotNull(e); } album = albumManager.getAlbum(album.getId()); assertNotNull(album); assertEquals(0,album.getPhotos().size()); } // end testAddAndRemoveAlbum2 /** * * @throws Exception */ public void testAddAndRemovePhoto() throws Exception { Album album = new Album(); //album = (Album) populate(album); album.setName("iiiiiiiii"); album.setOwnerDisplayName("ssssssssss"); album.setOwnerId(new Long(-10)); //album = albumManager.addAlbum(album); Photo photo = new Photo(); photo.setCover(Boolean.FALSE); photo.setOwnerId(new Long(8)); photo.setPhotoPostfix(".jpg"); photo.setTitle("xxxxxxxxxxxxxxxxxxxxxx"); photo.setAlbum(album); album.getPhotos().add(photo); // 这句话必须设上,不然后面album的photos里面找不到。 photo = albumManager.addPhoto(photo); assertNotNull(photo.getId()); assertEquals("xxxxxxxxxxxxxxxxxxxxxx",photo.getTitle()); assertEquals("iiiiiiiii",photo.getAlbum().getName()); long albumId = photo.getAlbum().getId(); album = this.albumManager.getAlbum(albumId); assertEquals(1,album.getPhotos().size()); log.debug("removing photo..."); long photoId = photo.getId(); /** * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Hibernate之deleted object would be re-saved by cascade 异常的解决 * 解决关联关系后,再删除 : * * 还有其他几种解决方案: * 1) 删除Set方的cascade——将Photo类中对album的cascade属性删掉。 * 2) */ album.removePhoto(photo); photo.setAlbum(null); albumManager.removePhoto(photoId); try { photo = albumManager.getPhoto(photoId); fail("Photo found in database"); } catch (DataAccessException e) { log.debug("Expected exception: " + e.getMessage()); assertNotNull(e); } /** * function getAlbumPhotoCount{ * String hql = "select count(*) from Photo as ph where ph.album = ? "; List ul = getHibernateTemplate().find(hql,new Object[]{al}); * } * 如果不在前面删除album和photo的关联,当执行到这句话时,会报"deleted object would be re-saved by cascade"异常。 * 调试发现,执行getAlbum(),album中的photos应是懒加载的,但仍然加载了,可以判断是因为一级缓存没有更新的缘故。 */ album = albumManager.getAlbum(albumId); assertNotNull(album); assertEquals(0,album.getPhotos().size()); } // end testAddAndRemovePhoto 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-08-02
假如数据量比较大的话 最好不做关联
|
|
返回顶楼 | |
发表时间:2009-08-02
photo.setAlbum(album);
photoManager.save(photo); |
|
返回顶楼 | |
发表时间:2009-08-02
herowzz 写道 photo.setAlbum(album);
photoManager.save(photo); 这个写法的前提是photo作为一对多关系的主控端吧! 但是我设置album和photo的双向一对多关系时,发现好像只能是由album作为主控端,查了很多资料也是这么写的。。。 而以前用多对多关系的时候,两边谁做主控端都可以的。 一对多却只能一的一端做主控端,所以很苦恼! 不知道上面的兄弟是如何做到让photo做一对多关系维护的主控端的。 p.s. 我的配置如下: @Entity @Table(name="alb_album") public class Album implements Serializable { private Set<Photo> photos = new HashSet<Photo>(); @OneToMany(cascade=CascadeType.ALL,mappedBy="album",fetch=FetchType.LAZY) public Set<Photo> getPhotos() { return photos; } public void setPhotos(Set<Photo> photos) { this.photos = photos; } } @Entity @Table(name="alb_photo") public class Photo implements Serializable{ private Album album; @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }) @JoinColumn(name="album_id") public Album getAlbum() { return album; } public void setAlbum(Album album) { this.album = album; } } |
|
返回顶楼 | |