হাইবারনেট জেপিএ সিকোয়েন্স (নন-আইডি)


138

কোনও কলামের জন্য ডিবি সিকোয়েন্স ব্যবহার করা সম্ভব যা সনাক্তকারী নয় / কোনও সংমিশ্রণ শনাক্তকারীর অংশ নয় ?

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

আমি যা চাই তা হ'ল সত্তার জন্য নতুন মান তৈরি করতে একটি সিক্যুয়েন্স ব্যবহার করা, যেখানে সিক্যুয়েন্সটির কলামটি মূল কী (অংশটির) নয় :

@Entity
@Table(name = "MyTable")
public class MyEntity {

    //...
    @Id //... etc
    public Long getId() {
        return id;
    }

   //note NO @Id here! but this doesn't work...
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "myGen")
    @SequenceGenerator(name = "myGen", sequenceName = "MY_SEQUENCE")
    @Column(name = "SEQ_VAL", unique = false, nullable = false, insertable = true, updatable = true)
    public Long getMySequencedValue(){
      return myVal;
    }

}

তারপরে আমি যখন এটি করি:

em.persist(new MyEntity());

আইডি উত্পন্ন করা হবে, তবে mySequenceValসম্পত্তিটি আমার জেপিএ সরবরাহকারীও তৈরি করবে।

কেবল বিষয়গুলি পরিষ্কার করার জন্য: আমি চাই হাইবারনেটটিmySequencedValue সম্পত্তিটির মান উত্পন্ন করতে । আমি জানি হাইবারনেট ডাটাবেস-উত্পন্ন মানগুলি পরিচালনা করতে পারে, তবে আমি আমার সম্পত্তিটির মান উত্পন্ন করতে হাইবারনেট নিজেই কোনও ট্রিগার বা অন্য কোনও জিনিস ব্যবহার করতে চাই না। হাইবারনেট যদি প্রাথমিক কীগুলির জন্য মান উত্পন্ন করতে পারে তবে কেন এটি কোনও সাধারণ সম্পত্তি তৈরি করতে পারে না?

উত্তর:


76

এই সমস্যার উত্তর খুঁজছি, আমি এই লিঙ্কে হোঁচট খেয়েছি

দেখে মনে হচ্ছে হাইবারনেট / জেপিএ আপনার অ-আইডি-বৈশিষ্ট্যের জন্য স্বয়ংক্রিয়ভাবে কোনও মান তৈরি করতে সক্ষম নয়। @GeneratedValueটীকাটি কেবল @Idঅটো-সংখ্যা তৈরি করতে ব্যবহৃত হয় ।

@GeneratedValueটীকা শুধু হাইবারনেট বলে যে ডাটাবেসের এই মান নিজেই উৎপাদিত হয়।

এই ফোরামে প্রস্তাবিত সমাধান (বা কাজের আশেপাশে) হ'ল একটি উত্পন্ন আইডির সাথে একটি পৃথক সত্তা তৈরি করা, এরকম কিছু:

@Entity
পাবলিক ক্লাস জেনারেল সেকেন্স নাম্বার {
  @ আইডি বলেন,
  @GeneratedValue (...)
  ব্যক্তিগত দীর্ঘ সংখ্যা;
}

@Entity 
পাবলিক ক্লাস MyEntity {
  @ আইডি ..
  প্রাইভেট লং আইডি;

  @একের পর এক(...)
  বেসরকারী জেনারেল সেকনস নাম্বার মাইভাল;
}

@ জেনারেটভ্যালুর জাভা ডক থেকে: "জেনারেটেডভ্যালু টিকাটি কোনও সত্তার প্রাথমিক কী সম্পত্তি বা ক্ষেত্রের ক্ষেত্রে প্রয়োগ করা যেতে পারে বা
আইড এনোটোটেশনের

11
আমি দেখতে পেলাম যে @ কলম (কলামডিফিনিশন = "সিরিয়াল") নিখুঁতভাবে কাজ করে তবে কেবল পোস্টগ্র্যাসকিউএল এর জন্য। আমার জন্য এটি নিখুঁত সমাধান ছিল, কারণ দ্বিতীয় সত্তাটি "
কুরুচিপূর্ণ

@ সার্জিভেদার্নিকভ যেটি অত্যন্ত সহায়ক ছিল । আপনি কি আলাদা উত্তর হিসাবে পোস্ট করতে আপত্তি করবেন? এটি আমার সমস্যাটি খুব সহজ এবং কার্যকরভাবে সমাধান করেছে।
ম্যাট বল

আমি আলাদা উত্তর :) হিসাবে এই পোস্ট করেছেন @MattBall stackoverflow.com/a/10647933/620858
সের্গেই Vedernikov

1
@GeneratedValueআইডি নয় এমন ক্ষেত্রগুলিতে অনুমতি দেওয়ার জন্য আমি একটি প্রস্তাব খুলেছি । 2.2 অন্তর্ভুক্ত করা দয়া করে ভোট দিন java.net/jira/browse/JPA_SPEC-113
Petar Tahchiev

44

আমি দেখতে পেয়েছি যে @Column(columnDefinition="serial")নিখুঁত কাজ করে তবে কেবল পোস্টগ্র্যাসকিউএল এর জন্য। আমার জন্য এটি নিখুঁত সমাধান ছিল, কারণ দ্বিতীয় সত্তাটি "কুশ্রী" বিকল্প।


হাই, আমি এটি সম্পর্কে একটি ব্যাখ্যা প্রয়োজন। আপনি আমাকে আরও বলতে পারেন?
ইমবার্সা

2
@ এমবার্সা columnDefinition=বিটটি মূলত হিবিরেটকে বলেছে যে কলাম সংজ্ঞা তৈরি করার চেষ্টা করবেন না এবং পরিবর্তে আপনি যে পাঠ্য দিয়েছেন তা ব্যবহার করুন। মূলত, কলামটির জন্য আপনার ডিডিএল আক্ষরিক অর্থে নাম + কলামডিফিনেশন হবে। এই ক্ষেত্রে (PostgreSQL), mycolumn serialএকটি সারণীতে একটি বৈধ কলাম।
প্যাট্রিক

7
মাইএসকিউএল এর সমতুল্য@Column(columnDefinition = "integer auto_increment")
রিচার্ড কেনার্ড

2
এই অটো কি এর মান উত্পন্ন করে? আমি ক্ষেত্রের সংজ্ঞা দিয়ে এর সাথে একটি সত্তাকে জেদ করার চেষ্টা করেছি তবে এটির কোনও মান উত্পন্ন হয়নি। এটি <কলাম <
b

7
আমি @Column(insertable = false, updatable = false, columnDefinition="serial")হাইবারনেটকে নাল মান সন্নিবেশ করানোর চেষ্টা করতে বা ক্ষেত্রটি আপডেট করতে বাধা দিতাম । তারপরে sertোকানোর পরে জেনারেটেড আইডি পাওয়ার জন্য আপনাকে ডিবিটিকে পুনরায় জিজ্ঞাসা করতে হবে যদি সরাসরি এটি ব্যবহার করার প্রয়োজন হয়।
রবার্ট ডি পাওলো

20

আমি জানি এটি একটি খুব পুরানো প্রশ্ন, তবে এটি প্রথমদিকে ফলাফলের উপর প্রদর্শিত হয়েছে এবং প্রশ্ন থেকে জেপিএ অনেক পরিবর্তন হয়েছে।

এখনই করার সঠিক @Generatedউপায়টি টীকা সহ। আপনি ক্রমটি সংজ্ঞায়িত করতে পারেন, কলামটিতে সেই অনুক্রমের জন্য ডিফল্ট সেট করতে পারেন এবং তারপরে কলামটি ম্যাপ করতে পারেন:

@Generated(GenerationTime.INSERT)
@Column(name = "column_name", insertable = false)

1
এটি এখনও ডাটাবেস দ্বারা উত্পন্ন মান প্রয়োজন, যা সত্যই প্রশ্নের উত্তর দেয় না। 12c এর পূর্বে ওরাকল ডাটাবেসগুলির জন্য, মানটি তৈরি করতে আপনাকে এখনও একটি ডাটাবেস ট্রিগার লিখতে হবে।
বার্নি

9
এছাড়াও, এটি একটি হাইবারনেট টিকা, জেপিএ নয়।
caarlos0

14

হাইবারনেট অবশ্যই এটি সমর্থন করে। ডক্স থেকে:

"উত্পন্ন বৈশিষ্ট্য হ'ল বৈশিষ্ট্য যা তাদের মানগুলি ডাটাবেস দ্বারা উত্পন্ন হয় Typ মূলত, যখনই হাইবারনেট উত্পন্ন বৈশিষ্ট্যগুলি সংজ্ঞায়িত করে এমন কোনও সত্তার জন্য একটি এসকিউএল INSERT বা আপডেটের বিষয়টি প্রকাশ করে, তত্ক্ষণাত উত্পন্ন মানগুলি পুনরুদ্ধার করার জন্য একটি নির্বাচন পরে জারি করে ""

কেবল সন্নিবেশ করানোর সময় উত্পন্ন বৈশিষ্ট্যগুলির জন্য, আপনার সম্পত্তি ম্যাপিং (.hbm.xML) এর মতো দেখতে পাবেন:

<property name="foo" generated="insert"/>

সন্নিবেশ করানো এবং আপডেট করা আপনার সম্পত্তি মানচিত্রের আপডেট করার জন্য (.hbm.xML) এর মতো দেখতে পাবেন:

<property name="foo" generated="always"/>

দুর্ভাগ্যক্রমে, আমি জেপিএ জানি না, সুতরাং জেপিএর মাধ্যমে এই বৈশিষ্ট্যটি প্রকাশিত হয়েছে কিনা তা আমি জানি না (আমার সন্দেহ হয় সম্ভবত না)

বিকল্পভাবে, আপনার সন্নিবেশ এবং আপডেটগুলি থেকে সম্পত্তিটি বাদ দিতে এবং তারপরে "ম্যানুয়ালি" কল সেশন.রেফ্রেশ (আপত্তি); আপনি এটি সন্নিবেশ / আপডেট করার পরে ডাটাবেস থেকে উত্পন্ন মানটি লোড করতে পারেন।

এইভাবে আপনি সম্পত্তি inোকানো এবং আপডেট বিবৃতি ব্যবহার করা থেকে বাদ দেবেন:

<property name="foo" update="false" insert="false"/>

আবার, আমি জানি না যে জেপিএ এই হাইবারনেট বৈশিষ্ট্যগুলি প্রকাশ করে তবে হাইবারনেট তাদের সমর্থন করে।


1
@ জেনারেটেড টিকাটি উপরের এক্সএমএল কনফিগারেশনের সাথে মিলে যায়। আরও তথ্যের জন্য হাইবারনেট ডক্সের এই বিভাগটি দেখুন ।
এরিক

8

ফলোআপ হিসাবে এখানে এটি কীভাবে কাজ করতে পেলাম:

@Override public Long getNextExternalId() {
    BigDecimal seq =
        (BigDecimal)((List)em.createNativeQuery("select col_msd_external_id_seq.nextval from dual").getResultList()).get(0);
    return seq.longValue();
}

হাইবারনেট 4.2.19 এবং ওরাকল সহ একটি পরিবর্তন: SQLQuery sqlQuery = getSession().createSQLQuery("select NAMED_SEQ.nextval seq from dual"); sqlQuery.addScalar("seq", LongType.INSTANCE); return (Long) sqlQuery.uniqueResult();
হারুন

6

আমি @PrePersistটীকাটি ব্যবহার করে হাইবারনেটের সাথে ইউআইডি (বা সিকোয়েন্স) প্রজন্মটি স্থির করেছি :

@PrePersist
public void initializeUUID() {
    if (uuid == null) {
        uuid = UUID.randomUUID().toString();
    }
}

5

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

আমি সম্পত্তিটি ছাড়াই সিকোয়েন্স নামে একটি কাস্টম টীকা প্রবর্তন করে আমার জন্য এই সমস্যাটি সমাধান করেছি। এটি ক্ষেত্রগুলির জন্য কেবল একটি চিহ্নিতকারী যা একটি বর্ধিত ক্রম থেকে একটি মান নির্ধারণ করা উচিত।

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sequence
{
}

এই টীকাটি ব্যবহার করে আমি আমার সত্তাগুলি চিহ্নিত করেছি।

public class Area extends BaseEntity implements ClientAware, IssuerAware
{
    @Column(name = "areaNumber", updatable = false)
    @Sequence
    private Integer areaNumber;
....
}

জিনিসগুলি ডাটাবেসকে স্বাধীন রাখতে আমি সিকোয়েন্স নাম্বার নামে একটি সত্তা প্রবর্তন করি যা ক্রম বর্তমান মান এবং বর্ধিত আকার ধারণ করে। আমি ক্লাসের নামটিকে অনন্য কী হিসাবে বেছে নিয়েছি যাতে প্রতিটি সত্তা শ্রেণি তার নিজস্ব ক্রম পেতে পারে।

@Entity
@Table(name = "SequenceNumber", uniqueConstraints = { @UniqueConstraint(columnNames = { "className" }) })
public class SequenceNumber
{
    @Id
    @Column(name = "className", updatable = false)
    private String className;

    @Column(name = "nextValue")
    private Integer nextValue = 1;

    @Column(name = "incrementValue")
    private Integer incrementValue = 10;

    ... some getters and setters ....
}

শেষ পদক্ষেপ এবং সবচেয়ে কঠিন হ'ল একটি PreInsertListener যা সিকোয়েন্স নম্বর অ্যাসাইনমেন্ট পরিচালনা করে। নোট করুন যে আমি বসন্তটি শিমের ধারক হিসাবে ব্যবহার করেছি।

@Component
public class SequenceListener implements PreInsertEventListener
{
    private static final long serialVersionUID = 7946581162328559098L;
    private final static Logger log = Logger.getLogger(SequenceListener.class);

    @Autowired
    private SessionFactoryImplementor sessionFactoryImpl;

    private final Map<String, CacheEntry> cache = new HashMap<>();

    @PostConstruct
    public void selfRegister()
    {
        // As you might expect, an EventListenerRegistry is the place with which event listeners are registered
        // It is a service so we look it up using the service registry
        final EventListenerRegistry eventListenerRegistry = sessionFactoryImpl.getServiceRegistry().getService(EventListenerRegistry.class);

        // add the listener to the end of the listener chain
        eventListenerRegistry.appendListeners(EventType.PRE_INSERT, this);
    }

    @Override
    public boolean onPreInsert(PreInsertEvent p_event)
    {
        updateSequenceValue(p_event.getEntity(), p_event.getState(), p_event.getPersister().getPropertyNames());

        return false;
    }

    private void updateSequenceValue(Object p_entity, Object[] p_state, String[] p_propertyNames)
    {
        try
        {
            List<Field> fields = ReflectUtil.getFields(p_entity.getClass(), null, Sequence.class);

            if (!fields.isEmpty())
            {
                if (log.isDebugEnabled())
                {
                    log.debug("Intercepted custom sequence entity.");
                }

                for (Field field : fields)
                {
                    Integer value = getSequenceNumber(p_entity.getClass().getName());

                    field.setAccessible(true);
                    field.set(p_entity, value);
                    setPropertyState(p_state, p_propertyNames, field.getName(), value);

                    if (log.isDebugEnabled())
                    {
                        LogMF.debug(log, "Set {0} property to {1}.", new Object[] { field, value });
                    }
                }
            }
        }
        catch (Exception e)
        {
            log.error("Failed to set sequence property.", e);
        }
    }

    private Integer getSequenceNumber(String p_className)
    {
        synchronized (cache)
        {
            CacheEntry current = cache.get(p_className);

            // not in cache yet => load from database
            if ((current == null) || current.isEmpty())
            {
                boolean insert = false;
                StatelessSession session = sessionFactoryImpl.openStatelessSession();
                session.beginTransaction();

                SequenceNumber sequenceNumber = (SequenceNumber) session.get(SequenceNumber.class, p_className);

                // not in database yet => create new sequence
                if (sequenceNumber == null)
                {
                    sequenceNumber = new SequenceNumber();
                    sequenceNumber.setClassName(p_className);
                    insert = true;
                }

                current = new CacheEntry(sequenceNumber.getNextValue() + sequenceNumber.getIncrementValue(), sequenceNumber.getNextValue());
                cache.put(p_className, current);
                sequenceNumber.setNextValue(sequenceNumber.getNextValue() + sequenceNumber.getIncrementValue());

                if (insert)
                {
                    session.insert(sequenceNumber);
                }
                else
                {
                    session.update(sequenceNumber);
                }
                session.getTransaction().commit();
                session.close();
            }

            return current.next();
        }
    }

    private void setPropertyState(Object[] propertyStates, String[] propertyNames, String propertyName, Object propertyState)
    {
        for (int i = 0; i < propertyNames.length; i++)
        {
            if (propertyName.equals(propertyNames[i]))
            {
                propertyStates[i] = propertyState;
                return;
            }
        }
    }

    private static class CacheEntry
    {
        private int current;
        private final int limit;

        public CacheEntry(final int p_limit, final int p_current)
        {
            current = p_current;
            limit = p_limit;
        }

        public Integer next()
        {
            return current++;
        }

        public boolean isEmpty()
        {
            return current >= limit;
        }
    }
}

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

আশা করি এটি কাউকে সাহায্য করবে।


5

আপনি যদি পোস্টগ্রেস্কএল ব্যবহার করছেন
এবং আমি স্প্রিং বুটে 1.5.6 ব্যবহার করছি

@Column(columnDefinition = "serial")
@Generated(GenerationTime.INSERT)
private Integer orderID;

1
এটি আমার জন্যও কাজ করেছিল, আমি স্প্রিং বুট ২.১..6. রিলিজ, হাইবারনেট ৫.৩.১০ ব্যবহার করছি।ফাইনাল, ইতিমধ্যে যা উল্লেখ করেছে সেগুলি ছাড়াও, আমাকে একটি সুরক্ষার ব্যবস্থা seq_orderএবং ক্ষেত্রের রেফারেন্স তৈরি করতে হয়েছিল, nextval('seq_order'::regclass)
ওজেভিএম

3

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

আমার সমাধানটি হল সম্পত্তিটি চালিয়ে যাওয়ার আগে হাত দিয়ে সেট করার জন্য দেশীয় জেপিএ ক্যোয়ারির সাথে ক্রমটি কল করা।

এটি সন্তোষজনক নয় তবে এটি মুহুর্তের জন্য কাজ হিসাবে কাজ করে।

মারিও


2

আমি এই নির্দিষ্ট নোটটি সেশন 9.1.9 এ পেয়েছি জেপিএর নির্দিষ্টকরণ থেকে উত্পন্ন জেনারেটেডভ্যালু টিকা: "[43] পোর্টেবল অ্যাপ্লিকেশনগুলিকে অন্য ধ্রুবক ক্ষেত্র বা সম্পত্তিগুলিতে জেনারেটভ্যালু টীকাটি ব্যবহার করা উচিত নয়" " সুতরাং, আমি অনুমান করি যে কমপক্ষে কেবল জেপিএ ব্যবহার করে অ প্রাথমিক কী মানগুলির জন্য স্বয়ংক্রিয়ভাবে উত্পাদন করা সম্ভব নয়।


1

থ্রেডটি পুরানো মনে হচ্ছে, আমি এখানে আমার সমাধানটি যুক্ত করতে চেয়েছিলাম (এস্পেক্টজে - বসন্তে এওপি ব্যবহার করে)।

সমাধান একটি কাস্টম টীকা তৈরি করা @InjectSequenceValueনিম্নরূপ।

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectSequenceValue {
    String sequencename();
}

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

এ জাতীয় টীকা

//serialNumber will be injected dynamically, with the next value of the serialnum_sequence.
 @InjectSequenceValue(sequencename = "serialnum_sequence") 
  Long serialNumber;

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

save/persistপদ্ধতিটি কার্যকর হওয়ার আগে আমরা ইঞ্জেকশনটি ট্রিগার করব his এটি নীচের শ্রেণিতে করা হয়।

@Aspect
@Configuration
public class AspectDefinition {

    @Autowired
    JdbcTemplate jdbcTemplate;


    //@Before("execution(* org.hibernate.session.save(..))") Use this for Hibernate.(also include session.save())
    @Before("execution(* org.springframework.data.repository.CrudRepository.save(..))") //This is for JPA.
    public void generateSequence(JoinPoint joinPoint){

        Object [] aragumentList=joinPoint.getArgs(); //Getting all arguments of the save
        for (Object arg :aragumentList ) {
            if (arg.getClass().isAnnotationPresent(Entity.class)){ // getting the Entity class

                Field[] fields = arg.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(InjectSequenceValue.class)) { //getting annotated fields

                        field.setAccessible(true); 
                        try {
                            if (field.get(arg) == null){ // Setting the next value
                                String sequenceName=field.getAnnotation(InjectSequenceValue.class).sequencename();
                                long nextval=getNextValue(sequenceName);
                                System.out.println("Next value :"+nextval); //TODO remove sout.
                                field.set(arg, nextval);
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        }
    }

    /**
     * This method fetches the next value from sequence
     * @param sequence
     * @return
     */

    public long getNextValue(String sequence){
        long sequenceNextVal=0L;

        SqlRowSet sqlRowSet= jdbcTemplate.queryForRowSet("SELECT "+sequence+".NEXTVAL as value FROM DUAL");
        while (sqlRowSet.next()){
            sequenceNextVal=sqlRowSet.getLong("value");

        }
        return  sequenceNextVal;
    }
}

এখন আপনি নীচের মতো যে কোনও সত্তাকে টিকা দিতে পারেন।

@Entity
@Table(name = "T_USER")
public class UserEntity {

    @Id
    @SequenceGenerator(sequenceName = "userid_sequence",name = "this_seq")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "this_seq")
    Long id;
    String userName;
    String password;

    @InjectSequenceValue(sequencename = "serialnum_sequence") // this will be injected at the time of saving.
    Long serialNumber;

    String name;
}

0

"আমি আমার সম্পত্তির মূল্য উত্পাদন করতে হাইবারনেট নিজেই ছাড়া ট্রিগার বা অন্য কোনও জিনিস ব্যবহার করতে চাই না"

সেক্ষেত্রে, ইউজারটাইপ যা একটি প্রয়োজনীয় মান উৎপন্ন করে এবং মাই সেকেন্সওয়াল সম্পত্তির অধ্যবসায়ের জন্য সেই ইউজারটাইপটি ব্যবহার করতে মেটাডাটা কনফিগার করে তা কার্যকরভাবে কীভাবে করা যায়?


0

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


0

যদি আপনার UNIQUEIDENTIFIER টাইপযুক্ত কলাম থাকে এবং defaultোকাতে ডিফল্ট প্রজন্মের প্রয়োজন হয় তবে কলামটি পিকে নয়

@Generated(GenerationTime.INSERT)
@Column(nullable = false , columnDefinition="UNIQUEIDENTIFIER")
private String uuidValue;

ডিবিতে আপনার হবে

CREATE TABLE operation.Table1
(
    Id         INT IDENTITY (1,1)               NOT NULL,
    UuidValue  UNIQUEIDENTIFIER DEFAULT NEWID() NOT NULL)

এক্ষেত্রে আপনার প্রয়োজনীয় মানটির জন্য আপনি জেনারেটরটি সংজ্ঞায়িত করবেন না (এটি স্বয়ংক্রিয়ভাবে ধন্যবাদ হবে columnDefinition="UNIQUEIDENTIFIER")। অন্যান্য কলামের ধরণের জন্য আপনি একই চেষ্টা করতে পারেন


0

আমি একটি স্প্রিং অ্যাপ্লিকেশনটিতে @ পোস্টকনস্ট্রাক্ট এবং জেডিবিসি টেম্পলেট ব্যবহার করে মাইএসকিএল ডেটাবেজে এটির জন্য একটি কার্যকারিতা পেয়েছি। এটি অন্যান্য ডাটাবেসের সাথে করণীয়যোগ্য হতে পারে তবে আমি যে ব্যবহারের ক্ষেত্রে উপস্থাপন করব তা মাইএসকিউএল-এর সাথে আমার অভিজ্ঞতার ভিত্তিতে তৈরি করা হয়েছে, কারণ এটি অটো_সংশোধন ব্যবহার করে।

প্রথমত, আমি @ কলাম টীকাটির কলামডিফাইনিশন সম্পত্তিটি ব্যবহার করে একটি কলামকে অটো_সংশোধক হিসাবে সংজ্ঞায়িত করার চেষ্টা করেছি, তবে এটি স্বয়ংক্রিয় বর্ধিত হওয়ার জন্য কলামটি কী হিসাবে কাজ করার প্রয়োজন ছিল না, তবে দৃশ্যত কলামটি সংজ্ঞায়িত হবে না সংজ্ঞায়িত হওয়ার পরে অবধি একটি সূচক, যার ফলে একটি অচলাবস্থার সৃষ্টি হয়।

এখানে আমি অটো_সামান্য সংজ্ঞা ছাড়াই কলাম তৈরি করার এবং ডেটাবেস তৈরি হওয়ার পরে এটি যুক্ত করার ধারণা নিয়ে এসেছি । এটি @ পোষ্টকনস্ট্রাক্ট টিকাটি ব্যবহার করেই সম্ভব, যার ফলে জেডবিসিটেমপ্লেটের আপডেট পদ্ধতির সাথে একত্রে অ্যাপ্লিকেশনটি মটরশুটি শুরু করার পরে ঠিক কোনও পদ্ধতি শুরু করা হয়।

কোডটি নিম্নরূপ:

আমার সত্তায়:

@Entity
@Table(name = "MyTable", indexes = { @Index(name = "my_index", columnList = "mySequencedValue") })
public class MyEntity {
    //...
    @Column(columnDefinition = "integer unsigned", nullable = false, updatable = false, insertable = false)
    private Long mySequencedValue;
    //...
}

পোস্টকন্সট্রাক্ট কম্পোনেন্ট শ্রেণিতে:

@Component
public class PostConstructComponent {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @PostConstruct
    public void makeMyEntityMySequencedValueAutoIncremental() {
        jdbcTemplate.update("alter table MyTable modify mySequencedValue int unsigned auto_increment");
    }
}

0

আমি @ মর্টেন বার্গের গৃহীত সমাধানের পাশে একটি বিকল্প সরবরাহ করতে চাই, যা আমার পক্ষে আরও ভাল কাজ করেছে।

এই পদ্ধতির পরিবর্তে ক্ষেত্রটি প্রকৃত পছন্দসই Numberধরণের - Longআমার ব্যবহারের ক্ষেত্রে - পরিবর্তে সংজ্ঞায়িত করতে দেয় GeneralSequenceNumber। এটি দরকারী হতে পারে, যেমন JSON (ডি-) সিরিয়ালাইজেশনের জন্য।

অবক্ষয়টি হ'ল এটির জন্য আরও একটু বেশি ডাটাবেস প্রয়োজন।


প্রথমত, আমাদের এমন একটি দরকার ActualEntityযাতে আমরা স্বয়ংক্রিয়ভাবে generatedপ্রকারের বৃদ্ধি করতে চাই Long:

// ...
@Entity
public class ActualEntity {

    @Id 
    // ...
    Long id;

    @Column(unique = true, updatable = false, nullable = false)
    Long generated;

    // ...

}

এর পরে, আমাদের একটি সহায়ক সত্তা প্রয়োজন Generated। প্যাকেজের ActualEntityবাস্তবায়নের বিশদ রাখার জন্য আমি এটি প্যাকেজ-প্রাইভেটের পাশে রেখেছি :

@Entity
class Generated {

    @Id
    @GeneratedValue(strategy = SEQUENCE, generator = "seq")
    @SequenceGenerator(name = "seq", initialValue = 1, allocationSize = 1)
    Long id;

}

শেষ অবধি, আমাদের সংরক্ষণ করার আগে আমাদের ডানদিকে toোকানোর জন্য একটি জায়গা প্রয়োজন ActualEntity। সেখানে, আমরা একটি Generatedউদাহরণ তৈরি করি এবং অবিরাম থাকি । এই তারপর একটি ডাটাবেস-ক্রম উত্পন্ন উপলব্ধ idধরনের Long। আমরা এই মানটি এটি লিখে লিখে ব্যবহার করিActualEntity.generated

আমার ব্যবহারের ক্ষেত্রে, আমি এটি একটি স্প্রিং ডেটা আরএসটি ব্যবহার করে বাস্তবায়ন করেছি @RepositoryEventHandler, যা প্রাপ্তি ActualEntityস্থির হওয়ার আগে ডেকে আনে। এটি নীতি প্রদর্শন করা উচিত:

@Component
@RepositoryEventHandler
public class ActualEntityHandler {

    @Autowired
    EntityManager entityManager;

    @Transactional
    @HandleBeforeCreate
    public void generate(ActualEntity entity) {
        Generated generated = new Generated();

        entityManager.persist(generated);
        entity.setGlobalId(generated.getId());
        entityManager.remove(generated);
    }

}

আমি এটি বাস্তব-জীবনে প্রয়োগে পরীক্ষা করিনি, সুতরাং দয়া করে যত্ন সহ উপভোগ করুন।


-1

আমি আপনার মতো পরিস্থিতিতে ছিলাম (জেপিএ / হাইবারনেট সিকোয়েন্সটি নন @ আইডি ফিল্ডের জন্য) এবং আমি আমার ডিবি স্কিমায় একটি ট্রিগার তৈরি করেছি যা সন্নিবেশে একটি অনন্য ক্রম সংখ্যা যুক্ত করে। আমি কখনই জেপিএ / হাইবারনেটের সাথে কাজ করতে পারি নি


-1

ঘন্টা ব্যয় করার পরে, এটি আমার সমস্যার সমাধান করতে খুব সুন্দরভাবে আমাকে সহায়তা করেছে:

ওরাকল 12 সি এর জন্য:

ID NUMBER GENERATED as IDENTITY

এইচ 2 এর জন্য:

ID BIGINT GENERATED as auto_increment

এছাড়াও করুন:

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