জেপিএ - অব্যাহত থাকার পরে একটি স্বয়ংক্রিয় উত্পন্ন আইডি ফিরিয়ে দেওয়া ()


113

আমি জেপিএ (এক্সপ্লিসলিঙ্ক) এবং স্প্রিং ব্যবহার করছি। বলুন আমার একটি স্বতঃ-উত্পন্ন ID সহ একটি সহজ সত্তা রয়েছে:

@Entity
public class ABC implements Serializable {
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     private int id;

     // ...
}

আমার ডিএও ক্লাসে আমার একটি সন্নিবেশ পদ্ধতি রয়েছে যা persist()এই সত্তাকে কল করে। আমি চাই যে পদ্ধতিটি নতুন সত্তার জন্য উত্পন্ন আইডিটি ফিরিয়ে দেবে, তবে আমি যখন এটি পরীক্ষা করি তখন এটি 0পরিবর্তে ফিরে আসে ।

public class ABCDao {
    @PersistenceContext
    EntityManager em;

    @Transactional(readOnly=false)
    public int insertABC(ABC abc) {
         em.persist(abc);
         // I WANT TO RETURN THE AUTO-GENERATED ID OF abc
         // HOW CAN I DO IT?
         return abc.id; // ???
    }
}

আমার কাছে একটি পরিষেবা শ্রেণিও রয়েছে যা ডিএওকে জড়িয়ে দেয়, যদি তাতে কোনও পার্থক্য আসে:

public class ABCService {
    @Resource(name="ABCDao")
    ABCDao abcDao;

    public int addNewABC(ABC abc) {
         return abcDao.insertABC(abc);
    }
}


উত্তরের জন্য ধন্যবাদ। এবং একটি জটিল সমাধান হিসাবে (জেপিএ নয়) আমরা ইউনিক্স টাইমস্ট্যাম্পের মতো আরও একটি অনন্য আইডি ব্যবহার করতে পারি।
সুরা 2 কে

উত্তর:


184

আইডিটি কেবল ফ্লাশ সময়ে উত্পন্ন হওয়ার গ্যারান্টিযুক্ত। একটি সত্তা থাকা কেবল স্থিরতা প্রসঙ্গে "সংযুক্ত" করে তোলে। সুতরাং, হয় সুনির্দিষ্টভাবে সত্তা পরিচালককে ফ্লাশ করুন:

em.persist(abc);
em.flush();
return abc.getId();

অথবা সত্তার আইডির চেয়ে নিজেই ফেরত দিন। যখন লেনদেন শেষ হবে, ফ্লাশ হবে এবং লেনদেনের বাইরের সত্তার ব্যবহারকারীরা এভাবে সত্তায় উত্পন্ন আইডি দেখতে পাবেন।

@Override
public ABC addNewABC(ABC abc) {
    abcDao.insertABC(abc);
    return abc;
}

10
এনবি: এটির সাথে আইডি ক্ষেত্রটি এনেটেট করা দরকার @GeneratedValue- যা কিছু
প্রবিষ্ট হয়

তোমার দর্শন লগ করা যৌগিক আইডি সহ এই অর্জন করার চেষ্টা বিষয় ব্যাখ্যা দয়া করে করতে পারেন stackoverflow.com/questions/31362100/...
bl3e

স্থির থাকার পরে ম্যানুয়ালি ফ্লাশিংয়ের পারফরম্যান্স পেনাল্টি (বা অন্য কোনও নেতিবাচক প্রভাব) রয়েছে কি?
ক্রেগ ওটিস

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

1
@ জেবিনিজেট, আপনার কি পুনরায় উপস্থিতি দরকার বা পাস হওয়া রেফারেন্সটি এখনও বৈধ? মানে, কোনও insertABCনতুন অবজেক্ট তৈরি করে ? নাকি পুরানোটিকে সংশোধন করবেন?
রাইভ্যানেজ

13
@Entity
public class ABC implements Serializable {
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     private int id;   
}

আপনার সত্তা শ্রেণিতে @ জেনারেটেডভ্যালু নোটেশন রয়েছে কিনা পরীক্ষা করুন his এটি জেপিএকে আপনার সত্তা সম্পত্তি স্বয়ংক্রিয়ভাবে উত্পন্ন আচরণ সম্পর্কে বলে


4

আমি এটি এইভাবে করেছি:

EntityManager entityManager = getEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(object);
transaction.commit();
long id = object.getId();
entityManager.close();

তথ্যটি টেবিলের মধ্যে রাখার পরে শূন্যকে রিটার্ন হিসাবে কাজ করছে না। হয় রিফ্রেশ এই ক্ষেত্রে কাজ করছে না .. আমি এই জন্য কি করা উচিত। দয়া করে একটি উপায় প্রস্তাব করুন ... ধন্যবাদ
বিক্রান্ত কাশ্যপ

1
@ বিক্রান্তকশ্যপ দয়া করে ছোট কোড সহ একটি নতুন প্রশ্ন পোস্ট করুন এবং আমাকে উল্লেখ করুন যাতে আমি একবার নজর দিতে পারি।
Koray Tugay

2

আপনি পরিচয়ের পরিবর্তে জেনারেশন টাইপ.ট্যাবল ব্যবহার করতে পারেন যা কেবল সন্নিবেশের পরে পাওয়া যায়।


2
সতর্কতার শুধু একটি শব্দ। আমি যখন জেনারেশন টাইপ.ট্যাবল চেষ্টা করেছিলাম তখন এটি হাইবারনেট_সেক্সেন্স নামে একটি পৃথক টেবিল তৈরি করেছিল এবং 1 থেকে ক্রমটি পুনরায় শুরু করেছিল
শ্রীশ্রী

0

৪.০ এর সাথে সামঞ্জস্যপূর্ণ অন্য একটি বিকল্প:

পরিবর্তনগুলি সম্পাদন করার আগে, আপনি CayenneDataObjectপ্রসঙ্গের সাথে সম্পর্কিত সংগ্রহ থেকে নতুন অবজেক্ট (গুলি) পুনরুদ্ধার করতে পারেন :

CayenneDataObject dataObjectsCollection = (CayenneDataObject)cayenneContext.newObjects();

তারপরে ObjectIdসংগ্রহের প্রতিটিটির জন্য অ্যাক্সেস করুন , যেমন:

ObjectId objectId = dataObject.getObjectId();

অবশেষে আপনি মানগুলির অধীনে পুনরাবৃত্তি করতে পারেন, যেখানে মানচিত্রে সাধারণত উত্পাদিত-আইডি মানকগুলির প্রথম এক (একক কলাম কী জন্য) হতে চলেছে getIdSnapshot(), এতে পিকে সম্পর্কিত কলামের নামও রয়েছে কী (গুলি) হিসাবে:

objectId.getIdSnapshot().values()

0

এইভাবে আমি এটি করেছি। আপনি চেষ্টা করতে পারেন

    public class ABCService {
    @Resource(name="ABCDao")
    ABCDao abcDao;

    public int addNewABC(ABC abc) {
         ABC.setId(0);
         return abcDao.insertABC(abc);
    }
}

-3
em.persist(abc);
em.refresh(abc);
return abc;

এই পদ্ধতিটি আমার পক্ষে কার্যকর হয়নি। এই ত্রুটিটি পেয়েছেন: javax.persistance.PersistanceException: org.hibernate.HibernateException: এই উদাহরণটি এখনও ডাটাবেসে সারি হিসাবে উপস্থিত নেই]
rtcarlson

@ আর্টকার্লসন, হ্যাঁ এটি কাজ করবে না। আপনি যদি একটি নতুন অবজেক্ট তৈরি করে থাকেন তবে আপনার যা প্রয়োজন তা em.flush()নয় em.refresh(abc)
ইব্রাহিম দাউদা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.