হাইবারনেট ত্রুটি: একই শনাক্তকারকের মানযুক্ত একটি পৃথক বস্তু ইতিমধ্যে সেশনের সাথে সম্পর্কিত ছিল


94

এই কনফিগারেশনে মূলত আমার কাছে কিছু অবজেক্ট রয়েছে (আসল ডেটা মডেলটি খানিকটা জটিল):

  • বি এর সাথে এ-এর অনেকগুলি সম্পর্ক রয়েছে (বি আছে inverse="true")
  • সি এর সাথে বি এর একাধিক এক সম্পর্ক রয়েছে (আমি cascadeসেট করে রেখেছি "save-update")
  • সি এক ধরণের টাইপ / ক্যাটাগরি সারণী।

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

আমার ডেটা দিয়ে আমি মাঝে মাঝে এমন সমস্যায় পড়ে যাই যেখানে A এর বি বিভিন্ন বি অবজেক্টের সেট থাকে এবং এই বি অবজেক্ট একই সি অবজেক্টকে বোঝায়।

আমি যখন কল session.saveOrUpdate(myAObject), আমি বলার অপেক্ষা রাখে না একটি হাইবারনেট ত্রুটি পাবেন: "a different object with the same identifier value was already associated with the session: C"। আমি জানি হাইবারনেট একই সেশনে দু'বার একই বস্তু সন্নিবেশ / আপডেট / মুছতে পারে না, তবে এর কোনও উপায় আছে কি? এটি এমন পরিস্থিতির অস্বাভাবিক হবে বলে মনে হয় না।

এই সমস্যা সম্পর্কে আমার গবেষণা চলাকালীন, আমি লোকেরা ব্যবহারের পরামর্শ দিতে দেখেছি session.merge(), কিন্তু যখন আমি এটি করি তখন কোনও "বিবাদমান" বিষয়বস্তু ডাটাবেসে সমস্ত মান বাতিল করে রেখে ফাঁকা বস্তু হিসাবে .োকানো হয়। স্পষ্টত এটি আমরা চাই না।

[সম্পাদনা] অন্য একটি জিনিস আমি উল্লেখ করতে ভুলে গেছি তা হ'ল (আমার নিয়ন্ত্রণের বাইরে স্থাপত্যগত কারণে), প্রতিটি পড়া বা লেখার আলাদা সেশনে করা দরকার।


দেখুন এই উত্তরটি আপনাকে সহায়তা করে কিনা ..
joonlima

উত্তর:


98

সম্ভবত সম্ভবত এর কারণ বি অবজেক্টগুলি একই জাভা সি অবজেক্টের উদাহরণটিকে উল্লেখ করছে না। তারা ডাটাবেসে একই সারি উল্লেখ করছে (অর্থাত্ একই প্রাথমিক কী) তবে তারা এর বিভিন্ন অনুলিপি।

সুতরাং যা হ'ল হায়বারনেট সেশন, যা সত্তাগুলি পরিচালনা করছে তা ট্রাফিক রাখবে যে জাভা অবজেক্টটি একই প্রাথমিক কী সহ সারিটির সাথে মিল রাখে।

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


4
ধন্যবাদ জেবিএক্স। যেমনটি আপনি বলেছিলেন, দেখা গেছে যে বি অবজেক্টগুলি মেমরির একাধিক সি উদাহরণগুলিতে উল্লেখ করছে। মূলত যা ঘটছে তা হ'ল আমার প্রোগ্রামের একটি অংশ সি পড়ছে, এবং এটি বিতে সংযুক্ত হচ্ছে অন্য অংশটি ডাটাবেস থেকে একই সি দিয়ে একটি আলাদা বি লোড করছে। উভয়ই এ-এর সাথে যুক্ত হচ্ছে যা সংরক্ষণে ত্রুটিটি ট্রিগার করে। আমি বি-> সি সম্পর্কের জন্য <p>> ক্যাসকেড </ translation> সেট করে রেখেছি "<p>> কিছুই নয় </ translation>", তবে আমি এখনও একই ত্রুটি পাচ্ছি। একাধিক টু-ওয়ান বা এক-একের মধ্যে সম্পর্কের ক্ষেত্রে হাইবারনেটকে কেবল বিদেশী কী পরিবর্তন করতে এবং বাকীগুলি নিয়ে চিন্তা না করার কোনও উপায় আছে কি?
জন

4
সি এর প্রাথমিক কীতে কোনও আইডি উত্পন্ন কৌশল আছে? সিকোয়েন্স-জেনারেটরের মতো বা এরকম কিছু?
jbx

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

14
আমি SaveOrUpdate () এবং BOOM এর পরিবর্তে মার্জ () ব্যবহার করেছি! এটি কাজ করে :)
লাহিরু রুহুনেগে

29

মার্জটিতে কেবল ক্যাসকেড সেট করুন, সেই কৌশলটি করা উচিত।


13

আপনার কেবল একটি কাজ করা দরকার। চালান session_object.clear()এবং তারপরে নতুন বস্তুটি সংরক্ষণ করুন। এটি সেশনটি সাফ করবে (যথাযথ নাম হিসাবে) এবং আপনার অধিবেশন থেকে আপত্তিকর সদৃশ বস্তুকে সরিয়ে দেবে।


10

আমি @ হেমন্ত কুমারের সাথে একমত, আপনাকে অনেক ধন্যবাদ তার সমাধান অনুযায়ী, আমি আমার সমস্যা সমাধান করেছি।

উদাহরণ স্বরূপ:

@Test
public void testSavePerson() {
    try (Session session = sessionFactory.openSession()) {
        Transaction tx = session.beginTransaction();
        Person person1 = new Person();
        Person person2 = new Person();
        person1.setName("222");
        person2.setName("111");
        session.save(person1);
        session.save(person2);
        tx.commit();
    }
}

ব্যক্তি.জাভা

public class Person {
    private int id;
    private String name;

    @Id
    @Column(name = "id")
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

এই কোডটি আমার অ্যাপ্লিকেশনটিতে সর্বদা ভুল A different object with the same identifier value was already associated with the sessionকরে :, পরে আমি জানতে পারি যে আমি আমার প্রাথমিক কীটি স্বায়ত্তশাসন করতে ভুলে গেছি !

আমার সমাধানটি হ'ল এই কোডটি আপনার প্রাথমিক কীতে যুক্ত করা:

@GeneratedValue(strategy = GenerationType.AUTO)

6

এর অর্থ আপনি একই টেক্সটে একই বস্তুর রেফারেন্স সহ একাধিক সারি সংরক্ষণ করার চেষ্টা করছেন।

আপনার সত্তা শ্রেণীর আইডি সম্পত্তি পরীক্ষা করুন।

@Id
private Integer id;

প্রতি

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private Integer id;

4
বর্ণিত বিবরণ অনুসারে প্রশ্নের সাথে নয়
সুদীপ ভান্ডারী

5

হাইবারনেট থেকে ডাটাবেসে অবজেক্ট আইডি নির্ধারণের কাজটি ব্যবহার করে স্থানান্তর করুন:

<generator class="native"/>

এটি আমার জন্য সমস্যার সমাধান।



3

উপরের সমস্যাটি সমাধানের একটি উপায় হ'ল ওভাররাইড করা hashcode()
সেভ করার আগে এবং পরে হাইবারনেট সেশনটি ফ্লাশ করুন।

getHibernateTemplate().flush();

সুস্পষ্টভাবে বিচ্ছিন্ন বস্তুকে সেট করা nullসহায়তা করে।


2

এই বার্তাটি জুড়ে এসেছে তবে সি # কোডে। নিশ্চিত না এটি প্রাসঙ্গিক কিনা (ঠিক একই ত্রুটির বার্তা যদিও)।

আমি ব্রেকপয়েন্ট সহ কোডটি ডিবাগ করছিলাম এবং ব্যক্তিগত সদস্যদের মাধ্যমে কিছু সংগ্রহ প্রসারিত করছিলাম যখন ডিবাগার একটি ব্রেকপয়েন্টে ছিল। কাঠামোগুলি খনন না করে কোডটি পুনরায় চালানো ত্রুটির বার্তাটি দূরে সরিয়ে দেয়। দেখে মনে হচ্ছে যে ব্যক্তিগত অলস-বোঝা সংগ্রহগুলি অনুসন্ধানের কাজটি এনএইচবারনেট লোড জিনিসগুলিকে তৈরি করেছিল যা সেই সময় লোড হওয়ার কথা ছিল না (কারণ তারা ব্যক্তিগত সদস্য ছিল)।

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

আশা করি এই সমস্যাটি জুড়ে অন্য কারও কাছে একটি সূত্র রয়েছে।


2

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


1

আমার এই ত্রুটিটি কয়েক দিন যেতে হয়েছিল এবং আমি এই ত্রুটিটি ঠিক করতে খুব বেশি সময় দিয়েছি।

 public boolean save(OrderHeader header) {
    Session session = sessionFactory.openSession();


    Transaction transaction = session.beginTransaction();

    try {
        session.save(header);

        for (OrderDetail detail : header.getDetails()) {
            session.save(detail);
        }

        transaction.commit();
        session.close();

        return true;
    } catch (HibernateException exception) {

        exception.printStackTrace();
        transaction.rollback();
        return false;
    }
}

আমি এই ত্রুটিটি পাওয়ার আগে, আমি অর্ডারডিটিল অবজেক্টে আইডি প্রজন্মের ধরণের উল্লেখ করিনি। যখন অর্ডারডেটেলস আইডি তৈরি না করে এটি প্রতিটি অর্ডারডেটল অবজেক্টের জন্য আইডি 0 হিসাবে রাখে। এটি # জেবিএক্স ব্যাখ্যা করেছে। হ্যাঁ এটি সেরা উত্তর। এটি কিভাবে ঘটে তা এই একটি উদাহরণ।


1

আপনার কোয়েরির কোডটি আগে রাখার চেষ্টা করুন। এটা আমার সমস্যা সমাধান। যেমন এটি পরিবর্তন করুন:

query1 
query2 - get the error 
update

এটি:

query2
query1
update

0

আপডেট ক্যোয়ারী কল করার আগে আপনি হয়ত সেই অবজেক্টের শনাক্তকারীকে সেট করছেন না।


4
তিনি না থাকলে তাঁর এই সমস্যা হত না। সমস্যাটি হ'ল একই শনাক্তকারী সহ তাঁর দুটি জিনিস রয়েছে।
aalku

0

প্রাথমিক কী প্রজন্মটি ভুল হওয়ার কারণে আমি সমস্যার মুখোমুখি হয়েছি, যখন আমি এই জাতীয় একটি সারিটি sertোকান:

public void addTerminal(String typeOfDevice,Map<Byte,Integer> map) {
        // TODO Auto-generated method stub
        try {
            Set<Byte> keySet = map.keySet();
            for (Byte byte1 : keySet) {
                Device device=new Device();
                device.setNumDevice(DeviceCount.map.get(byte1));
                device.setTimestamp(System.currentTimeMillis());
                device.setTypeDevice(byte1);
                this.getHibernateTemplate().save(device);
            }
            System.out.println("hah");
        }catch (Exception e) {
            // TODO: handle exception
            logger.warn("wrong");
            logger.warn(e.getStackTrace()+e.getMessage());
        }
}

আমি আইডি জেনারেটর ক্লাস পরিচয় পরিবর্তন

<id name="id" type="int">
    <column name="id" />
    <generator class="identity"  />
 </id>

0

আমার ক্ষেত্রে কেবল ফ্লাশ () কাজ করেনি। ফ্লাশ () এর পরে আমাকে একটি পরিষ্কার () ব্যবহার করতে হয়েছিল।

public Object merge(final Object detachedInstance)
    {
        this.getHibernateTemplate().flush();
        this.getHibernateTemplate().clear();
        try
        {
            this.getHibernateTemplate().evict(detachedInstance);
        }
}


0

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


0

নিশ্চিত করুন, আপনার সত্তার সমস্ত ম্যাপযুক্ত সত্তার সাথে একই প্রজন্মের প্রকার রয়েছে

প্রাক্তন: ইউজাররোল

public class UserRole extends AbstractDomain {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String longName;

private String shortName;

@Enumerated(EnumType.STRING)
private CommonStatus status;

private String roleCode;

private Long level;

@Column(columnDefinition = "integer default 0")
private Integer subRoleCount;

private String modification;

@ManyToOne(fetch = FetchType.LAZY)
private TypeOfUsers licenseType;

}

মডিউল:

public class Modules implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String longName;

private String shortName;

}

ম্যাপিংয়ের সাথে প্রধান সত্ত্বা

public class RoleModules implements Serializable{

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
private UserRole role;

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
private Modules modules;

@Type(type = "yes_no")
private boolean isPrimaryModule;

public boolean getIsPrimaryModule() {
    return isPrimaryModule;
}

}


0

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


0

শুধু বর্তমান লেনদেন প্রতিশ্রুতিবদ্ধ।

currentSession.getTransaction().commit();

এখন আপনি অন্য একটি লেনদেন শুরু করতে পারেন এবং সত্তা যেকোন কিছু করতে পারেন


0

আর একটি ক্ষেত্রে যখন একই ত্রুটি বার্তা তৈরি করা যায়, কাস্টম allocationSize:

@Id
@Column(name = "idpar")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "paramsSequence")
@SequenceGenerator(name = "paramsSequence", sequenceName = "par_idpar_seq", allocationSize = 20)
private Long id;

মিলছে না

alter sequence par_idpar_seq increment 20;

সন্নিবেশের সময় বাধার বৈধতা সৃষ্টি করতে পারে (যেটি বোঝা সহজ) বা "একই শনাক্তকারীর মানযুক্ত একটি পৃথক বস্তু ইতিমধ্যে সেশনের সাথে যুক্ত ছিল" - এই ক্ষেত্রেটি কম স্পষ্ট ছিল না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.