org.hibernate.PersistanceObjectException: বিচ্ছিন্নভাবে সত্তা অস্তিত্ব বজায় রেখেছিল


90

আমি হাইবারনেট সহ সফলভাবে আমার প্রথম মাস্টার সন্তানের উদাহরণ লিখেছি। কিছু দিন পরে আমি এটি আবার নিয়েছি এবং কিছু গ্রন্থাগার আপগ্রেড করেছি। আমি কী করেছি তা নিশ্চিত নয় তবে আমি এটি আর কখনও চালাতে পারি না। কেউ কি আমার চিত্রটি ভুল হিসাবে চিহ্নিত করতে কোডের মধ্যে ভুল যা বার বার ফিরে আসছে:

org.hibernate.PersistentObjectException: detached entity passed to persist: example.forms.InvoiceItem
    at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)
    at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:799)
    at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:791)
    .... (truncated)

হাইবারনেট ম্যাপিং:

<hibernate-mapping package="example.forms">
    <class name="Invoice" table="Invoices">
        <id name="id" type="long">
            <generator class="native" />
        </id>
        <property name="invDate" type="timestamp" />
        <property name="customerId" type="int" />
        <set cascade="all" inverse="true" lazy="true" name="items" order-by="id">
            <key column="invoiceId" />
            <one-to-many class="InvoiceItem" />
        </set>
    </class>
    <class name="InvoiceItem" table="InvoiceItems">
        <id column="id" name="itemId" type="long">
            <generator class="native" />
        </id>
        <property name="productId" type="long" />
        <property name="packname" type="string" />
        <property name="quantity" type="int" />
        <property name="price" type="double" />
        <many-to-one class="example.forms.Invoice" column="invoiceId" name="invoice" not-null="true" />
    </class>
</hibernate-mapping>

সম্পাদনা: ইনভয়েস ম্যানেজ.আরভা

class InvoiceManager {

    public Long save(Invoice theInvoice) throws RemoteException {
        Session session = HbmUtils.getSessionFactory().getCurrentSession();
        Transaction tx = null;
        Long id = null;
        try {
            tx = session.beginTransaction();
            session.persist(theInvoice);
            tx.commit();
            id = theInvoice.getId();
        } catch (RuntimeException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
            throw new RemoteException("Invoice could not be saved");
        } finally {
            if (session.isOpen())
                session.close();
        }
        return id;
    }

    public Invoice getInvoice(Long cid) throws RemoteException {
        Session session = HbmUtils.getSessionFactory().getCurrentSession();
        Transaction tx = null;
        Invoice theInvoice = null;
        try {
            tx = session.beginTransaction();
            Query q = session
                    .createQuery(
                            "from Invoice as invoice " +
                            "left join fetch invoice.items as invoiceItems " +
                            "where invoice.id = :id ")
                    .setReadOnly(true);
            q.setParameter("id", cid);
            theInvoice = (Invoice) q.uniqueResult();
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
        } finally {
            if (session.isOpen())
                session.close();
        }
        return theInvoice;
    }
}

চালান.জভা

public class Invoice implements java.io.Serializable {

    private Long id;
    private Date invDate;
    private int customerId;
    private Set<InvoiceItem> items;

    public Long getId() {
        return id;
    }

    public Date getInvDate() {
        return invDate;
    }

    public int getCustomerId() {
        return customerId;
    }

    public Set<InvoiceItem> getItems() {
        return items;
    }

    void setId(Long id) {
        this.id = id;
    }

    void setInvDate(Date invDate) {
        this.invDate = invDate;
    }

    void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    void setItems(Set<InvoiceItem> items) {
        this.items = items;
    }
}

চালান আইটেম.জভা

public class InvoiceItem implements java.io.Serializable {

    private Long itemId;
    private long productId;
    private String packname;
    private int quantity;
    private double price;
    private Invoice invoice;

    public Long getItemId() {
        return itemId;
    }

    public long getProductId() {
        return productId;
    }

    public String getPackname() {
        return packname;
    }

    public int getQuantity() {
        return quantity;
    }

    public double getPrice() {
        return price;
    }

    public Invoice getInvoice() {
        return invoice;
    }

    void setItemId(Long itemId) {
        this.itemId = itemId;
    }

    void setProductId(long productId) {
        this.productId = productId;
    }

    void setPackname(String packname) {
        this.packname = packname;
    }

    void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    void setPrice(double price) {
        this.price = price;
    }

    void setInvoice(Invoice invoice) {
        this.invoice = invoice;
    }
}

সম্পাদনা: ক্লায়েন্টের কাছ থেকে জেএসএন অবজেক্ট পাঠানো হয়েছে:

{"id":null,"customerId":3,"invDate":"2005-06-07T04:00:00.000Z","items":[
{"itemId":1,"productId":1,"quantity":10,"price":100},
{"itemId":2,"productId":2,"quantity":20,"price":200},
{"itemId":3,"productId":3,"quantity":30,"price":300}]}

সম্পাদনা: কিছু বিশদ:
আমি দুটি উপায় অনুসরণ করে চালানটি সংরক্ষণ করার চেষ্টা করেছি:

  1. উপরে উল্লিখিত জসন অবজেক্টটি ম্যানুয়ালি বানানো এবং এটিকে সার্ভারের নতুন সেশনে পাস করা হয়েছে। এক্ষেত্রে সেভ পদ্ধতিতে কল করার আগে একেবারে কোনও কার্যক্রম করা হয়নি তাই সেভ পদ্ধতিতে খোলা একটি ব্যতীত আর কোনও খোলা অধিবেশন হওয়া উচিত নয় should

  2. GetInvoice পদ্ধতি ব্যবহার করে বিদ্যমান ডেটা লোড করে এবং কী মানটি সরানোর পরে তারা একই ডেটা পাস করেছে। এটিও আমি বিশ্বাস করি সংরক্ষণের আগে সেশনটি বন্ধ করে দেওয়া উচিত কারণ গেটইনভয়েস পদ্ধতিতে লেনদেন হচ্ছে।

উভয় ক্ষেত্রেই আমি একই ত্রুটি বার্তা পাচ্ছি যা আমাকে বিশ্বাস করতে বাধ্য করছে যে হাইবারনেট কনফিগারেশন ফাইল বা সত্তা শ্রেণি বা সংরক্ষণ পদ্ধতিতে কিছু ভুল আছে।

আমার আরও বিশদ সরবরাহ করা উচিত কিনা দয়া করে আমাকে জানান

উত্তর:


120

আপনি অনেক প্রাসঙ্গিক বিশদ সরবরাহ করেন নি তাই আমি অনুমান করব যে আপনি কল করেছিলেন getInvoiceএবং তারপরে আপনি কিছু মান নির্ধারণের জন্য ফলাফল অবজেক্টটি ব্যবহার করেছিলেন এবং এই saveধারণাটি সহ কল করেছিলেন যে আপনার অবজেক্টের পরিবর্তনগুলি সংরক্ষণ হবে।

তবে persistঅপারেশনটি ব্র্যান্ডের নতুন ক্ষণস্থায়ী বস্তুর জন্য এবং আইডি ইতিমধ্যে বরাদ্দ করা থাকলে এটি ব্যর্থ হয়। আপনার ক্ষেত্রে আপনি সম্ভবত এর saveOrUpdateপরিবর্তে কল করতে চান persist

আপনি এখানে কিছু আলোচনা এবং রেফারেন্স পেতে পারেন "জেপিএ / ইজেবি কোড সহ" বিচ্ছিন্নতা বজায় রাখতে বিচ্ছিন্ন সত্তা "


আপনাকে ধন্যবাদ অ্যালেক্স গিটেলম্যান। আমি আমার মূল প্রশ্নের নীচে কিছু বিশদ যুক্ত করেছি। এটা আমার সমস্যা বুঝতে সাহায্য করে? বা দয়া করে আমাকে জানুন যে অন্যান্য বিশদ কী সহায়ক হবে।
ডাব্লুএসকে

7
আপনার রেফারেন্স আমাকে বোকা ভুল খুঁজে পেতে সহায়তা করেছিল। চাইল্ড টেবিলে প্রাথমিক কী এটি "আইটেমআইডি" এর জন্য আমি নাল মান পাঠাচ্ছিলাম না। তাই হাইবারনেট এমন ধারণা তৈরি করছিল যে কোনও সেশনে ইতিমধ্যে বস্তুটি বিদ্যমান exists পরামর্শের জন্য আপনাকে ধন্যবাদ
WSK

এখন আমি এই ত্রুটিটি পাচ্ছি: "org.hibernate.PropertyValueException: নাল সম্পত্তি নয় একটি নাল বা ক্ষণস্থায়ী মান উল্লেখ করে: উদাহরণ.ફોর্মস.আইনভয়েসআইটেম.invoice"। আপনি আমাকে কিছু ইঙ্গিত দিতে পারেন? অগ্রিম ধন্যবাদ
WSK

আপনার অস্থায়ী নয়, স্থির অবস্থায় চালান থাকতে হবে। এর অর্থ এই যে ইতিমধ্যে আইডি অবশ্যই নিয়োগ করা উচিত। Invoiceপ্রথমে সেভ করুন , সুতরাং এটি আইডি পাবে এবং তারপরে সেভ করবে InvoiceItem। আপনি ক্যাসকেডিং দিয়ে খেলতেও পারেন।
অ্যালেক্স গিটেলম্যান

14

এখানে আপনি নেটিভ ব্যবহার করেছেন এবং প্রাথমিক কীতে নির্ধারণের মানটি, স্থানীয় প্রাথমিক কীতে স্বয়ংক্রিয়ভাবে উত্পন্ন হয়।

সুতরাং বিষয়টি আসছে।


4
যদি আপনি বিশ্বাস করেন যে ইতিমধ্যে একটি স্বীকৃত উত্তর রয়েছে এমন কোনও প্রশ্নের জন্য প্রস্তাব দেওয়ার জন্য আপনার কাছে অতিরিক্ত তথ্য রয়েছে তবে দয়া করে আরও যথেষ্ট ব্যাখ্যা প্রদান করুন।
শিকাগো রেডসক্স

11

এটি @ManToOne সম্পর্কের মধ্যে বিদ্যমান। আমি ক্যাসকেডটাইপ.মার্সটি বা ক্যাসকেডটাইপ.এলএল এর পরিবর্তে কেবল ক্যাসকেডটাইপ.মার্গই ব্যবহার করে এই সমস্যাটি সমাধান করেছি। আশা করি এটি আপনাকে সহায়তা করবে।

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="updated_by", referencedColumnName = "id")
private Admin admin;

সমাধান:

@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name="updated_by", referencedColumnName = "id")
private Admin admin;

4

সম্ভবত আপনি যে কোডটি আমাদের এখানে দেখিয়ে দিচ্ছেন সম্ভবত সমস্যাটি তার বাইরে রয়েছে। আপনি বর্তমান সেশনের সাথে সম্পর্কিত নয় এমন একটি বিষয় আপডেট করার চেষ্টা করছেন। যদি এটি চালান না হয়, তবে সম্ভবত এটি একটি ইনভয়েসআইটেম যা ইতিমধ্যে স্থায়ীভাবে ডিবি থেকে প্রাপ্ত, কোনও ধরণের সেশনে জীবিত রাখা হয়েছে এবং তারপরে আপনি এটি একটি নতুন অধিবেশনটিতে চালিয়ে যাওয়ার চেষ্টা করবেন। সপ্তাহের দিন. একটি সাধারণ নিয়ম হিসাবে, আপনার অবিচলিত অবজেক্টগুলি কখনই সেশন জুড়ে জীবিত রাখবেন না।

সমাধানটি একই অধিবেশন থেকে পুরো অবজেক্ট গ্রাফটি প্রাপ্ত করার সাথে সাথে আপনি এটি চালিয়ে যাওয়ার চেষ্টা করছেন। ওয়েব পরিবেশে এর অর্থ হবে:

  • অধিবেশন প্রাপ্ত
  • আপনার প্রয়োজনীয় সংস্থাগুলি আপডেট করতে বা সংযুক্ত করতে যুক্ত করতে হবে Fet তাদের প্রাথমিক কী দ্বারা অগ্রাধিকারযোগ্য
  • যা প্রয়োজন তা পরিবর্তন করুন
  • আপনি যা চান সেভ / আপডেট / উচ্ছেদ / মুছে দিন
  • আপনার সেশন / লেনদেন বন্ধ / প্রতিশ্রুতিবদ্ধ

আপনার সমস্যাটি যদি এমন কিছু কোড পোস্ট করে যা আপনার পরিষেবাটিকে কল করে।


আপনাকে ধন্যবাদ @ জুস্টসচাউটেন স্পষ্টতই সেভ পদ্ধতিতে কল করার আগে ওপেন সেশন হওয়া উচিত নয় যেহেতু আমি "আরও বিশদ" তে উল্লেখ করেছি যে আমি নীচে আমার মূল প্রশ্নটি যুক্ত করেছি। আমি কীভাবে সেভ পদ্ধতিতে কল করার আগে কোনও সেশন উপস্থিত রয়েছে কিনা তা পরীক্ষা করে দেখার কোন উপায় আছে কি?
ডাব্লুএসকে

আপনার ধারণা "" সম্ভবত সংরক্ষণের পদ্ধতিটি কল করার আগে ওপেন সেশন হওয়া উচিত নয় "ভুল is আপনার ক্ষেত্রে আপনি প্রতিটি সেভের চারপাশে একটি লেনদেন মোড়ছেন এবং পাবেন যার অর্থ খোলা সেশনগুলি হওয়া উচিত নয় এবং যদি সেগুলি কোনও কাজে আসে না। আপনার সমস্যাটি মনে হয় যে কোডটি আপনার জেএসওএন পরিচালনা করে। এখানে আপনি চালান আইটেমগুলির সাথে একটি চালান পাস করুন যা ইতিমধ্যে বিদ্যমান (তাদের আইডি রয়েছে)। নাল আইডি দিয়ে পাস করুন এবং এটি সম্ভবত কার্যকর হবে। অথবা আপনার পরিষেবাটি হ্যান্ডলিং করে ডিএসের কাছ থেকে চালিত চালানগুলি চালান করুন, চালানে যুক্ত করুন এবং আপনি যে একই সেশন থেকে পেয়েছেন সেগুলিতে সেভ করুন।
জাস্টসচাউটেন

@ জুস্টাচাউটেন এখন আমি এই ত্রুটিটি পাচ্ছি: "org.hibernate.PopertyValueException: নাল সম্পত্তি হ'ল নাল বা ক্ষণস্থায়ী মানের উল্লেখ করে: উদাহরণ.ફોর্মস.আইনভয়েসআইটেম.invoice"। আপনি আমাকে কিছু ধারণা দিতে পারেন? অগ্রিম ধন্যবাদ
ডাব্লুএসকে

4
এটি আমার কাছে নতুন প্রশ্নের মতো মনে হচ্ছে। আপনি আমাদের সাথে একটি গুরুত্বপূর্ণ কোডের অংশ ভাগ করে নিলেন না। যে কোডটি JSON এর সাথে ডিল করে, আপনার মডেল অবজেক্টস এবং কলগুলি অবিচ্ছিন্ন এবং সংরক্ষণ করে। এই ব্যতিক্রম আপনাকে জানায় যে আপনি নাল চালান সহ একটি চালান আইটেমটি চালিয়ে যাওয়ার চেষ্টা করছেন। যা সঠিকভাবে করা যায় না। দয়া করে কোডটি পোস্ট করুন যা প্রকৃতপক্ষে আপনার মডেল অবজেক্টগুলি তৈরি করে।
জোরস্টচাউটেন

@ জুস্টসচাউটেন এটি আমার কাছে বোধগম্য হয় তবে সমস্যাটি হ'ল আমি জেএসএনের জন্য একটি ফ্রেমওয়ার্ক "কিউক্সডু" ব্যবহার করছি এবং সার্ভারে আরপিসি কল তৈরি করছি যেখানে আমার একই কাঠামো থেকে আরপিসি সার্ভারের ইউটিলিটি ইনস্টল করা আছে। সুতরাং সবকিছু ফ্রেমওয়ার্ক ক্লাসে আবৃত। হাজার হাজার লাইন উত্তোলন এবং পোস্ট করা ব্যবহারিক নাও হতে পারে। অন্যদিকে সার্ভারের পাশে তৈরি করা হয়েছে "দ্য ইনভয়েস" অবজেক্টটি আমরা দেখতে পারি? বা হাইবারনেট ডিবাগ / ট্রেস তথ্য দেখিয়ে?
ডাব্লুএসকে

2

দুটি সমাধান ১. আপনি যদি নতুন অবজেক্টটি আপডেট করতে চান তবে মার্জটি ব্যবহার করুন ২. আপনি কেবল নতুন অবজেক্টটি সংরক্ষণ করতে চাইলে সেভ ব্যবহার করুন (নিশ্চিত করুন পরিচয়টি হাইবারনেট বা ডাটাবেসটিকে উত্পন্ন করতে দেয় না) ৩. আপনি যদি ম্যাপিং ব্যবহার করছেন তবে
মার্জটি @OneToOne এর করছেন ( ফেচ = ফেচটাইপ.এগ্রার, ক্যাসকেড = ক্যাসকেডটাইপ.এল) @ জয়েন কলাম (নাম = "স্টক_আইডি")

তারপরে ক্যাসকেডটাইপ.আরএলকে ক্যাসকেডটাইপ.মার্গে ব্যবহার করুন

ধন্যবাদ শহীদ আব্বাসী


1

আমার "একই" সমস্যা ছিল কারণ আমি লিখছিলাম

@GeneratedValue(strategy = GenerationType.IDENTITY)

আমি এই লাইনটি মুছে ফেলেছি কারণ এই মুহুর্তে আমার এটির দরকার নেই, আমি বস্তুগুলি এবং তাই দিয়ে পরীক্ষা করছিলাম। আমি ভাবছি এটাই সেটা<generator class="native" /> আপনার ক্ষেত্রে আছে

আমার কোনও নিয়ামক নেই এবং আমার এপিআই অ্যাক্সেস হচ্ছে না, এটি কেবল পরীক্ষার জন্য (এই মুহুর্তে)।


0

জেপিএ জন্য স্থির () পরিবর্তে অ্যান্টিটি ম্যানেজার মার্জ () ব্যবহার করে স্থির করা হয়েছে

EntityManager em = getEntityManager();
    try {
        em.getTransaction().begin();
        em.merge(fieldValue);
        em.getTransaction().commit();
    } catch (Exception e) {
        //do smthng
    } finally {
        em.close();
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.