স্প্রিং @ ট্রান্সজেকশনাল অ্যাট্রিবিউট কি কোনও ব্যক্তিগত পদ্ধতিতে কাজ করে?


195

যদি আমার কাছে একটি স্প্রিং শিমের একটি ব্যক্তিগত পদ্ধতিতে @ ট্রান্সজেকশনাল- নোটেশন থাকে, তবে টীকাটির কোনও প্রভাব আছে?

যদি @Transactionalটীকাগুলি কোনও সর্বজনীন পদ্ধতিতে থাকে তবে এটি কাজ করে এবং একটি লেনদেন খুলবে।

public class Bean {
  public void doStuff() {
     doPrivateStuff();
  }
  @Transactional
  private void doPrivateStuff() {

  }
}

...

Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();

উত্তর:


162

প্রশ্নটি ব্যক্তিগত বা পাবলিক নয়, প্রশ্নটি হল: এটি কীভাবে আবেদন করা হয় এবং আপনি কোন এওপি বাস্তবায়ন ব্যবহার করেন!

আপনি যদি (ডিফল্ট) স্প্রিং প্রক্সি এওপি ব্যবহার করেন, তবে স্প্রিংয়ের (যেমন @Transational) সরবরাহিত সমস্ত এওপি কার্যকারিতা কেবলমাত্র কল প্রক্সি দিয়ে গেলে বিবেচনায় নেওয়া হবে। - যদি টীকাযুক্ত পদ্ধতিটি অন্য শিম থেকে ডাকা হয় তবে এটি সাধারণত হয় ।

এর দুটি জড়িত প্রভাব রয়েছে:

  • যেহেতু ব্যক্তিগত পদ্ধতিগুলি অবশ্যই অন্য শিম থেকে নেওয়া উচিত নয় (ব্যতিক্রমটি প্রতিবিম্ব) তবে তাদের @Transactionalটীকাকে বিবেচনায় নেওয়া হয় না।
  • যদি পদ্ধতিটি সর্বজনীন হয় তবে এটি একই শিম থেকে আহ্বান করা হয় তবে এটিও বিবেচনায় নেওয়া হবে না (এই বিবৃতিটি সঠিক হলেই (ডিফল্ট) স্প্রিং প্রক্সি এওপি ব্যবহার করা হয়)।

@ স্প্রিং রেফারেন্স দেখুন: অধ্যায় 9.6 9.6 প্রক্সি পদ্ধতি

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


4
উভয় পয়েন্ট অগত্যা সত্য নয়। প্রথমটি ভুল - ব্যক্তিগত পদ্ধতিগুলি প্রতিবিম্বিতভাবে আহ্বান করা যেতে পারে, তবে প্রক্সি আবিষ্কার করার যুক্তিটি তা না করার পছন্দ করে। দ্বিতীয় পয়েন্টটি কেবল ইন্টারফেস-ভিত্তিক জেডিকে প্রক্সির ক্ষেত্রেই সত্য, তবে সিজিএলআইবি সাবক্লাস-ভিত্তিক প্রক্সিগুলির জন্য নয়।
skaffman

@ স্কাফম্যান: 1 - আমি আমার স্ট্যাটমেন্টটি আরও সুনির্দিষ্ট করে তুলি, ২. তবে ডিফল্ট প্রক্সিটি ইন্টারফেস ভিত্তিক - তাই না?
রাল্ফ

2
লক্ষ্য নির্ভর করে যে ইন্টারফেস ব্যবহার করে কিনা। যদি এটি না হয় তবে সিজিএলআইবি ব্যবহৃত হয়।
skaffman

ক্যানু আমাকে বলুন রেসন বা কিছু রেফারেন্স কেন সিজিবিব পারসপেক্টস ছাড়া পারে না?
ফিলি

1
উত্তর ব্লকের লিঙ্কটি থেকে রেফারেন্স, যদি আপনি স্প্রিং প্রক্সি [ডিফল্ট পরিবেশ] ব্যবহার করতে চান তবে doStuff () এ টীকাটি লিখুন এবং ((বিন) অ্যাওপন্টেস্টেক্সট কর্নারপ্রক্রি ()) ব্যবহার করে doPrivateStuff () কল করুন; doPrivateStuff (); যদি প্রচারটি পুনরায় চালিত হয় [ডিফল্ট পরিবেশ] environment
মাইকেল ওইয়াং

218

আপনার প্রশ্নের উত্তরটি হ'ল না - @Transactional কোনও ব্যক্তিগত পদ্ধতিতে টীকাগুলি ব্যবহার করা হলে তার কোনও প্রভাব পড়বে না। প্রক্সি জেনারেটর এগুলি উপেক্ষা করবে।

এটি স্প্রিং ম্যানুয়াল অধ্যায় 10.5.6 এ নথিভুক্ত করা হয়েছে :

পদ্ধতির দৃশ্যমানতা এবং @Transactional

প্রক্সিগুলি ব্যবহার করার সময়, আপনাকে অবশ্যই @Transactionalজনসাধারণের দৃশ্যমানতার সাথে মেলে এমন পদ্ধতিতে টীকাটি প্রয়োগ করা উচিত । আপনি যদি টীকা সহ সুরক্ষিত, ব্যক্তিগত বা প্যাকেজ-দৃশ্যমান পদ্ধতিগুলি @Transactionalটীকাযুক্ত করেন, কোনও ত্রুটি উত্থাপিত হয় না, তবে টীকাযুক্ত পদ্ধতিটি কনফিগার করা লেনদেনের সেটিংস প্রদর্শন করে না। অ-পাবলিক পদ্ধতিতে টিকা দেওয়ার প্রয়োজন হলে অ্যাসপেক্টজে (নীচে দেখুন) ব্যবহার বিবেচনা করুন।


আপনি যদি এই বিষয়ে নিশ্চিত? আমি এটি একটি পার্থক্য করতে আশা করব না।
উইকোডেজেভাফফুড

প্রক্সিং শৈলীর Cglib হয় কিভাবে?
লিলি

32

ডিফল্টরূপে @Transactionalঅ্যাট্রিবিউটটি কেবলমাত্র অ্যাপ্লিকেশন কনটেক্সট থেকে প্রাপ্ত রেফারেন্সে কোনও টীকাযুক্ত পদ্ধতি কল করার সময় কাজ করে।

public class Bean {
  public void doStuff() {
    doTransactionStuff();
  }
  @Transactional
  public void doTransactionStuff() {

  }
}

এটি একটি লেনদেন খুলবে:

Bean bean = (Bean)appContext.getBean("bean");
bean.doTransactionStuff();

এটি করবে না:

Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();

বসন্ত রেফারেন্স: @ ট্রান্সজেকশনাল ব্যবহার করে

দ্রষ্টব্য: প্রক্সি মোডে (যা পূর্বনির্ধারিত), প্রক্সি দিয়ে আসা কেবলমাত্র 'বাহ্যিক' পদ্ধতি কলগুলি বাধা দেওয়া হবে। এর অর্থ হ'ল 'স্ব-আহ্বান', অর্থাত্ টার্গেট অবজেক্টের মধ্যে এমন একটি পদ্ধতি যা টার্গেট অবজেক্টের অন্য কোনও পদ্ধতিকে কল করে, রানটাইমে প্রকৃত লেনদেনের দিকে পরিচালিত করে না, এমনকি যদি অনুরোধ করা পদ্ধতিটি চিহ্নিত করা হয় if@Transactional !

অ্যাসপেক্টজে মোডের ব্যবহারটি বিবেচনা করুন (নীচে দেখুন) আপনি যদি স্ব-আহ্বানগুলিও লেনদেনের সাথে মোড়ানো বলে আশা করেন। এই ক্ষেত্রে, প্রথম স্থানে কোনও প্রক্সি থাকবে না; পরিবর্তে, @Transactionalকোনও ধরণের পদ্ধতিতে রানটাইম আচরণে রূপান্তর করতে লক্ষ্য শ্রেণিটি 'বুনা' হবে (অর্থাত্ এর বাইট কোডটি সংশোধন করা হবে) ।


আপনার অর্থ কি শিম = নতুন বিন () ;?
উইলকোডেজাভফুফড

নাঃ। আমি যদি নতুন শিম () দিয়ে মটরশুটি তৈরি করি, তবে টিকা কমপক্ষে Aspect-J ব্যবহার না করে কখনই কাজ করবে না।
জুহা সিরিজালি

2
ধন্যবাদ! এটি আমি যে অদ্ভুত আচরণটি পর্যবেক্ষণ করছিলাম তা ব্যাখ্যা করে। বেশ অভ্যন্তরীন এই অভ্যন্তরীণ পদ্ধতির
প্রার্থনা

আমি শিখেছি "প্রক্সি দিয়ে আসা কেবলমাত্র বাহ্যিক পদ্ধতি
কলগুলিই

13

হ্যাঁ, ব্যক্তিগত ব্যক্তিগত পদ্ধতিতে @ ট্রান্সজেকশনালটি ব্যবহার করা সম্ভব, তবে অন্যরা যেমন উল্লেখ করেছেন এটি বাক্সের বাইরে কাজ করবে না। আপনার AspectJ ব্যবহার করা উচিত। এটি কীভাবে কাজ করবে তা নির্ধারণ করতে আমার কিছুটা সময় লেগেছিল। আমি আমার ফলাফল ভাগ করে নেব।

লোড-টাইম ওয়েভিংয়ের পরিবর্তে আমি কমপাইল-টাইম ওয়েভিং ব্যবহার করা বেছে নিয়েছি কারণ আমি মনে করি এটি সামগ্রিক উন্নত বিকল্প। এছাড়াও, আমি জাভা 8 ব্যবহার করছি যাতে আপনার কিছু প্যারামিটারগুলি সামঞ্জস্য করতে হতে পারে।

প্রথমে, প্যাসেজজার্টের জন্য নির্ভরতা যুক্ত করুন।

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.8</version>
</dependency>

তারপরে মাভেনে আসল বাইটকোড বয়ন করতে AspectJ প্লাগইন যুক্ত করুন (এটি কোনও সর্বনিম্ন উদাহরণ নাও হতে পারে)।

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.8</version>
    <configuration>
        <complianceLevel>1.8</complianceLevel>
        <source>1.8</source>
        <target>1.8</target>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibraries>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

অবশেষে এটি আপনার কনফিগার ক্লাসে যুক্ত করুন

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)

এখন আপনার ব্যক্তিগত পদ্ধতিতে @ লেনদেন ব্যবহার করতে সক্ষম হওয়া উচিত।

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


যদি প্রক্সিং পদ্ধতিটি সিজিবিব হয়, তবে এমন একটি ইন্টারফেস প্রয়োগ করার দরকার নেই যা পদ্ধতিটি সর্বজনীন হওয়া উচিত, তবে এটি ব্যক্তিগত পদ্ধতিতে @ ট্রান্সজেকশনালটি ব্যবহার করতে সক্ষম হবে?
লিলি

হ্যাঁ, এটি ব্যক্তিগত পদ্ধতিতে এবং ইন্টারফেস ছাড়াই কাজ করে! যতক্ষণ AspectJ যথাযথভাবে কনফিগার করা থাকে ততক্ষণ এটি মূলত ওয়ার্কিং মেথড সজ্জকারদের গ্যারান্টি দেয়। এবং ব্যবহারকারী 5516১16১ তার উত্তরে উল্লেখ করেছেন যে এটি স্ব-অনুরোধগুলিতেও কাজ করবে। এটি সত্যিই দুর্দান্ত, এবং একটি সামান্য বিট ভীতিজনক।
জেমস ওয়াটকিন্স

12

আপনার যদি কোনও লেনদেনের মধ্যে একটি ব্যক্তিগত পদ্ধতি মোড়ানো প্রয়োজন এবং অধ্যায়টি ব্যবহার করতে না চান তবে আপনি ট্রানজেকশন টেম্পলেট ব্যবহার করতে পারেন ।

@Service
public class MyService {

    @Autowired
    private TransactionTemplate transactionTemplate;

    private void process(){
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                processInTransaction();
            }
        });

    }

    private void processInTransaction(){
        //...
    }

}

TransactionTemplateব্যবহার দেখানো ভাল , তবে দয়া করে ..RequiresTransactionতার চেয়ে দ্বিতীয় পদ্ধতিটি কল করুন ..InTransaction। আপনি কীভাবে এক বছর পরে এটি পড়তে চান তা সর্বদা স্টেমের নাম দিন। এছাড়াও আমি এটি ভাবতে বিতর্ক করব যে এটির জন্য যদি সত্যিই দ্বিতীয় কোনও ব্যক্তিগত পদ্ধতির প্রয়োজন হয়: হয় এটির বিষয়বস্তু সরাসরি বেনামে executeবাস্তবায়নের মধ্যে রাখুন বা যদি এটি অগোছালো হয়ে যায় তবে আপনি সম্ভবত বর্ণিত করতে পারেন এমন কোনও পরিষেবাতে প্রয়োগের বিভক্ত হওয়ার ইঙ্গিত হতে পারে @Transactional
আটকে

@ স্টক, দ্বিতীয় পদ্ধতিটি সত্যই প্রয়োজনীয় নয়, তবে এটি মূল প্রশ্নের উত্তর দেয় যা কীভাবে একটি ব্যক্তিগত পদ্ধতিতে বসন্তের লেনদেন প্রয়োগ করতে হয়
লুনিস

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

5

স্প্রিং ডক্স এটি ব্যাখ্যা করে

প্রক্সি মোডে (যা পূর্বনির্ধারিত), প্রক্সি দিয়ে আগত কেবলমাত্র বাহ্যিক পদ্ধতি কলগুলি বাধা দেওয়া হয়। এর অর্থ হ'ল স্ব-আহ্বান, ফলস্বরূপ, টার্গেট অবজেক্টের মধ্যে এমন একটি পদ্ধতি যা টার্গেট অবজেক্টের অন্য পদ্ধতিটিকে কল করে, রানটাইম সময়ে ডায়াল্ট পদ্ধতিটি @ ট্রান্সজেকশনাল দিয়ে চিহ্নিত করা হলেও সত্যিকারের লেনদেনের দিকে পরিচালিত করে না।

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

আরেকটি উপায় হ'ল ব্যবহারকারী বিয়ানসেল্ফওয়্যার


আপনি একটি রেফারেন্স যোগ করতে পারেন BeanSelfAware? এটা একটা স্প্রিং এর বর্গ মত দেখাচ্ছে না
asgs

@ এসএসজিস ধরুন, এটি সেলফ ইনজেকশন সম্পর্কে (একটি প্রকির সাথে নিজেকে আবৃত করার একটি শিম সরবরাহ করুন)। আপনি স্ট্যাকওভারফ্লো . com/q/3423972/355438 এ উদাহরণ দেখতে পাচ্ছেন ।
Lu55

3

উত্তর না হয়। দয়া করে বসন্তের রেফারেন্স দেখুন: @ ট্রান্সঅ্যাকশনাল ব্যবহার করে :

@Transactionalটীকা একটি ইন্টারফেস, একটি বর্গ সংজ্ঞা, অথবা একটি উপর, একটি ইন্টারফেস সংজ্ঞা সামনে স্থাপন করা যেতে পারে একটি পদ্ধতি পাবলিক একটি বর্গ উপর পদ্ধতি


1

মতো একই ভাবে @loonis প্রস্তাব ব্যবহার করতে TransactionTemplate এক এই সাহায্যকারী উপাদান (Kotlin) ব্যবহার করতে পারেন:

@Component
class TransactionalUtils {
    /**
     * Execute any [block] of code (even private methods)
     * as if it was effectively [Transactional]
     */
    @Transactional
    fun <R> executeAsTransactional(block: () -> R): R {
        return block()
    }
}

ব্যবহার:

@Service
class SomeService(private val transactionalUtils: TransactionalUtils) {

    fun foo() {
        transactionalUtils.executeAsTransactional { transactionalFoo() }
    }

    private fun transactionalFoo() {
        println("This method is executed within transaction")
    }
}

TransactionTemplateবিদ্যমান লেনদেন পুনরায় ব্যবহার করুন কিনা তা জানেন না তবে এই কোডটি অবশ্যই করবে definitely

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