我在一个POJO类中用到了component-set,然后在控制台打印查询结果。
结果是出来了,但是我对hibernate调用的相关SQL语句不解。
Hibernate: delete from image where product_id=? and filename=? and path=? and image_size=?
Hibernate: delete from image where product_id=? and filename=? and path=? and image_size=?
Hibernate: insert into image (product_id, filename, path, image_size) values (?, ?, ?, ?)
Hibernate: insert into image (product_id, filename, path, image_size) values (?, ?, ?, ?)
一个简单的查询,为什么hibernate会调用delete和insert? 

解决方案 »

  1.   

    您能把你在hibernate里调用的方法贴出来吗?
      

  2.   


    public void printProduct() {
    Session session=SessionFactoryUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction(); Product p=(Product)session.load(Product.class, 1);
    System.out.println(p.getProductid());
    System.out.println(p.getDescription());
    System.out.println(p.getName());
    System.out.println(p.getCreateTime());

    Set<Image> images=p.getImages();
    for(Image image:images) {
    System.out.println(image.getFilename());
    System.out.println(image.getPath());
    System.out.println(image.getImageSize());
    }

    session.getTransaction().commit();
    } public static void main(String[] args) {
    HibernateTest test = new HibernateTest();
    test.printProduct();
    }
      

  3.   

    Product.hbm.xml
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="com.szh.example.Product" table="product" catalog="test">
            <id name="productid" type="java.lang.Integer">
                <column name="productid" />
                <generator class="increment"></generator>
            </id>
            <property name="name" type="java.lang.String">
                <column name="name" />
            </property>
            <property name="price" type="java.lang.Double">
                <column name="price" precision="22" scale="0" />
            </property>
            <property name="description" type="java.lang.String">
                <column name="description" />
            </property>
            <property name="createTime" type="java.util.Date">
                <column name="create_time" length="19" />
            </property>
            <set name="images" table="image">
             <key column="product_id" foreign-key="product_id"></key>
             <composite-element class="com.szh.example.Image">
             <property name="filename" column="filename"></property>
             <property name="path" column="path"></property>
             <property name="imageSize" column="image_size"></property>
             </composite-element>
            </set>
        </class>
    </hibernate-mapping>
      

  4.   

    LZ光是查询的话可以尝试不用Transaction 我没用过这种映射方式 不过刚才搜索了小下
    你把这个去掉
           Set<Image> images=p.getImages();
            for(Image image:images) {
                System.out.println(image.getFilename());
                System.out.println(image.getPath());
                System.out.println(image.getImageSize());
            }
    你看看会输出什么
    不知道为什么要这么映射 不过在事务提交的时候他更新了某些东西 可能会跟你这个FOR循环有关系吧
    http://esffor.javaeye.com/blog/96313
      

  5.   

    原因应该出在你的Image类没有覆写hashCode和equals方法,set集合不能包含重复对象,hibernate无法判断是否重复,所以会先删除再插入。
      

  6.   

    补充:上面内容的后面部分写错了,如果Image类不覆写hashCode和equals方法,hibernate是可以判断重复行的,hibernate使用image的父类Object的hashCode方法来判断,此方法返回的是对象地址作为散列码,在事务commit的时候hibernate会加载所有set集合中的元素,再依次比较当前集合中元素,结果发现数据库中的元素都不在当前集合中,所以就会删除数据库中的元素,然后把当前集合中的元素当做新元素持久化到数据库中。
    因此就需要为Image类覆写hashCode和equals方法,让hibernate可以按业务正确判断是否重复。
      

  7.   

    悠西。。真不知道原来是根据hashCode来判断的。。我之前一直以为是根据持久化标识来判断的 阿弥陀佛。。
      

  8.   

    我是lz,问题解决了。
    为Product和Image类添加hashCode和equals方法后再查询,
    Hibernate就没有调用delete和insert了。
    感谢6楼,感谢大家对本问题的关注。
    散分!