`
rustlingwind
  • 浏览: 20858 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

使用hibernate开发相册时,相册与照片的一对多问题!

阅读更多
大家好!

我在做一个相册,每个相册中可能有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



分享到:
评论
3 楼 rustlingwind 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;
    }

}
2 楼 herowzz 2009-08-02  
photo.setAlbum(album);
photoManager.save(photo);
1 楼 zrzdemon 2009-08-02  
假如数据量比较大的话 最好不做关联

相关推荐

    J2EE网络相册管理系统.doc

    本文就是以此为背景,结合实际,从相关技术简介、需求及概要设计、详细设计及实现、实现效果、测试分析等几个方面详细阐述了一个能够对照片进行网络存储、在线搜索、在线编辑的网络相册管理系统的设计实现。...

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    由于客户端的硬件配置可能存在差异,软件环能各不相同,因此,在安装时,必须对每一个客户端分别进行配置,同样,在软件升级时也要对客户端分别处理。 B/S模式带来了巨大的好处: 开发成本及维护成本降低。由于B/S...

    基于J2EE框架的个人博客系统项目毕业设计论...

    由于客户端的硬件配置可能存在差异,软件环能各不相同,因此,在安装时,必须对每一个客户端分别进行配置,同样,在软件升级时也要对客户端分别处理。 B/S模式带来了巨大的好处: 开发成本及维护成本降低。由于B/S...

    JAVA上百实例源码以及开源项目源代码

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    JAVA上百实例源码以及开源项目

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    2个开源的BLOG

    使包括日记、照片、讨论均可使用标签 支持多种友情链接包括:WEB、WAP、RSS、站内等 全功能WAP支持 允许设置多个超级管理员对各个空间数据进行管理 技术 升级组件Hibernate-&gt;3.1.3, Strus-&gt;...

    java源码包---java 源码 大量 实例

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    java开源包8

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    火炬博客系统7

    软件及安装说明 &lt;br&gt; 本系统是一个Struts+Spring+Hibernate组合开发的博客系统,本系统使用分层体系架构,综合运用struts+spring+hibernate 三大主流开源框架构建,稳定高效、功能强大、易于维护。系统分为四个...

    火炬博客系统6

    软件及安装说明 &lt;br&gt; 本系统是一个Struts+Spring+Hibernate组合开发的博客系统,本系统使用分层体系架构,综合运用struts+spring+hibernate 三大主流开源框架构建,稳定高效、功能强大、易于维护。系统分为四个...

    iuhyiuhkjh908u0980

    一个组件可以有一个或多个支持它的数据库,因此,当装配两个或更多的组件时,我们希望能够保持在跨组件的多个数据库中进行的操作的原子性。J2EE服务器为这些组件提供了一个容器来保证事务原子性和跨组件独立性。如果...

    火炬博客系统5

    软件及安装说明 &lt;br&gt; 本系统是一个Struts+Spring+Hibernate组合开发的博客系统,本系统使用分层体系架构,综合运用struts+spring+hibernate 三大主流开源框架构建,稳定高效、功能强大、易于维护。系统分为四个...

    java源码包2

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 ...

    java开源包1

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包11

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java开源包2

    JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (&lt;jcaptcha:image label="Type the text "/&gt; ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...

    java源码包3

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 ...

Global site tag (gtag.js) - Google Analytics