zoukankan      html  css  js  c++  java
  • Hibernate之增删查改常见错误

    增:

    1、当一个对象有id值,如果数据库有这个id,你在create时执行的是保存操作,没有这个id,执行新建操作

     2、use与coupon之间有一个中间表usercoupon,下面这种添加usercoupon的方式会使与user对应的usercoupon的创建时间都会刷新,就像新建一样

    user.getCoupons().add(coupon);
    userService.save(user);

     所以下面这种方式好一点

                        UserCoupon uc=new UserCoupon();
                        uc.setCoupon(coupon);
                        uc.setUser(user);
                        userCouponService.create(uc);

    查:在一次查询类别表Type的所有对象,查询花了很长时间,发现不仅查了Type,还将type的set<SubType>属性赋值,即又查了SubType表

    ,SubType的set<Store>,Store的set<Coupon>........做了很多无用功,但是虽然配置了openSessionInViewFilter,但是这些set都是lazy加载啊

    调试发现

    (1)执行下面方法只查询了Type表

    @Override
        public List<T> listAll() {
            // TODO Auto-generated method stub
            String hql="from Type type  where type.deleted=false ";
            return list(hql, null);
        }

    (2)执行到以下代码时,开始疯狂查询和加载response.setObject(list);

    List<Type> list = typeService.listAll();
    response=new Response(0);
    response.setObject(list);

    原因:在setObject(list)的过程中,元素Type的set属性被初始化,并且从表填充数据

    (3)解决方法一

                    List<Type> list = typeService.listAll();
            response=new Response(0);
            for(int i=0;i<list.size();i++){
                list.get(i).setSubs(null);
            }
            response.setObject(list);

     解决方法二:只从查询结果区部分需要用到的字段,然后拼成一个新的对象返回

    coupons=couponService.list("select new Coupon(coupon.id,coupon.name) from Coupon coupon where coupon.store.id=:id Order by name", map);

     条件是有相应的构造函数(加了这个,还会org.hibernate.InstantiationException: No default constructor for entity:)

    所以还加个无参构造函数

        public Coupon(int id,String name) {
            super();
            this.name = name;
            this.setId(id);
        }

    改:修改优惠券coupon类

    /**
     * @author JL 优惠券实体类
     */
    @Entity
    @Table(name = "tb_coupon")
    public class Coupon extends BaseBean{
    
        /**
         * 编码
         */
        private String code;
        /**
         * 优惠券名称
         */
        private String name;
       /**
         * 优惠券所属商家
         */
        @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST,
                CascadeType.REFRESH }, fetch = FetchType.LAZY)    
        @JoinColumn(name = "store_id")
        private Store store;
        
        @ManyToMany(mappedBy="coupons",fetch = FetchType.LAZY,cascade=CascadeType.ALL)
        private List<User> users=new ArrayList<User>();
    
        @OneToOne
        @PrimaryKeyJoinColumn
        private CouponAd ad;
    
    }

    Store关于coupon的配置

        @OneToMany(mappedBy = "store", fetch = FetchType.LAZY)
        private Set<Coupon> coupons = new HashSet<Coupon>();

    表单文件jsp需要传入一个coupon的各个属性,包括外键:coupon.store.id

    保存修改的代码

            couponService.save(coupon);

    注意:

    (1)如果成员store有值,却没有提交coupon.store.id,则保存后store为null

    (2)如果成员store本身为null,你提交了coupon.store.id希望自动给他赋上store的值,那么save会报错:

    transient 瞬时态
    org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: com.life.hibernate.bean.Store; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.life.hibernate.bean.Store

    这时需要

            coupon.setStore(storeService.find(Store.class, coupon.getStore().getId()));
            couponService.save(coupon);

     (3)如果coupon.id的值没有传过去,很严重,这时不是保存,而是新建一条记录

    Done

  • 相关阅读:
    初识PL/SQL
    PL/SQL基本语法
    Oracle命令备忘
    工厂模式之二 工厂方法(Factory Method)
    XMLHttpRequest 原始AJAX初步
    DOM元素的innerHTML属性
    如果用JavaScript获取标准下拉框的"选中值"和"选中文本"
    工厂模式之三 抽象工厂(Abstract Factory)模式
    JavaScript中的动态参数
    JavaScript中的闭包初探
  • 原文地址:https://www.cnblogs.com/xingyyy/p/3907001.html
Copyright © 2011-2022 走看看