JPA- এ মান নির্ধারিত মান রয়েছে?


192

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

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

  public enum Right {
      READ(100), WRITE(200), EDITOR (300);

      private int value;

      Right(int value) { this.value = value; }

      public int getValue() { return value; }
  };

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "AUTHORITY_ID")
  private Long id;

  // the enum to map : 
  private Right right;
}

একটি সহজ সমাধান হ'ল এনিউমটাইপ.অর্ডিনাল সহ গণিত টীকাগুলি ব্যবহার করা:

@Column(name = "RIGHT")
@Enumerated(EnumType.ORDINAL)
private Right right;

তবে এক্ষেত্রে জেপিএ এনাম ইনডেক্স (0,1,2) মানচিত্র করে এবং আমি যে মান চাই তা নয় (100,200,300)।

আমি যে দুটি সমাধান পেয়েছি তা সহজ বলে মনে হচ্ছে না ...

প্রথম সমাধান

এখানে প্রস্তাবিত একটি সমাধান, এনামকে অন্য ক্ষেত্রে রূপান্তর করতে এবং এনাম ক্ষেত্রটিকে ক্ষণস্থায়ী হিসাবে চিহ্নিত করতে @PersPersist এবং @PostLoad ব্যবহার করে:

@Basic
private int intValueForAnEnum;

@PrePersist
void populateDBFields() {
  intValueForAnEnum = right.getValue();
}

@PostLoad
void populateTransientFields() {
  right = Right.valueOf(intValueForAnEnum);
}

দ্বিতীয় সমাধান

এখানে প্রস্তাবিত দ্বিতীয় সমাধানটিতে জেনেরিক রূপান্তর অবজেক্টের প্রস্তাব দেওয়া হয়েছে , তবে এখনও ভারী এবং হাইবারনেট-ভিত্তিক মনে হচ্ছে (@ টাইপ জাভা EE তে উপস্থিত বলে মনে হচ্ছে না):

@Type(
    type = "org.appfuse.tutorial.commons.hibernate.GenericEnumUserType",
    parameters = {
            @Parameter(
                name  = "enumClass",                      
                value = "Authority$Right"),
            @Parameter(
                name  = "identifierMethod",
                value = "toInt"),
            @Parameter(
                name  = "valueOfMethod",
                value = "fromInt")
            }
)

অন্য কোন সমাধান আছে কি?

আমার মনে বেশ কয়েকটি ধারণা রয়েছে তবে আমি জানি না যে এগুলি জেপিএতে রয়েছে কিনা:

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

7
অর্ডিনাল ব্যবহার করা আশ্চর্যজনক যেহেতু কেউ কেউ কখনও কখনও গণনার আইটেমগুলির স্থান পরিবর্তন করে এবং ডাটাবেস বিপর্যয়ে পরিণত হয়
নাতাশা কেপি

2
নাম ব্যবহারের ক্ষেত্রেও একই প্রযোজ্য হবে না - কেউ এনাম নাম (গুলি) পরিবর্তন করতে পারে এবং তারা আবার ডেটাবেসগুলির সাথে সিঙ্কের বাইরে চলে যায় ...
topchef

2
আমি @ নাটাসকেপিতে একমত অর্ডিনাল ব্যবহার করবেন না। নাম পরিবর্তনের জন্য, এ জাতীয় কোনও জিনিস নেই। আপনি আসলে পুরানো এনাম মুছে ফেলছেন এবং একটি নতুন নামের সাথে একটি নতুন যুক্ত করছেন, সুতরাং হ্যাঁ, কোনও সঞ্চিত ডেটা সিঙ্কের বাইরে থাকবে (শব্দার্থক, সম্ভবত: পি)।
সুইভেন হানসেন

হ্যাঁ এখানে 5 টি সমাধান রয়েছে যা আমি জানি। নীচে আমার উত্তর দেখুন, যেখানে আমার একটি বিস্তারিত উত্তর আছে।
ক্রিস রিচি

উত্তর:


168

জেপিএ ২.১ এর আগের সংস্করণগুলির জন্য, জেপিএ তাদের nameদ্বারা বা তাদের দ্বারা এনামগুলি নিয়ে ডিল করার জন্য কেবল দুটি উপায় সরবরাহ করে ordinal। এবং মানক জেপিএ কাস্টম ধরণের সমর্থন করে না। তাই:

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

আমি সর্বশেষ বিকল্পটি বর্ণনা করব (এটি একটি মৌলিক বাস্তবায়ন, এটি প্রয়োজনীয়ভাবে টুইট করুন):

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

    public enum Right {
        READ(100), WRITE(200), EDITOR (300);

        private int value;

        Right(int value) { this.value = value; }    

        public int getValue() { return value; }

        public static Right parse(int id) {
            Right right = null; // Default
            for (Right item : Right.values()) {
                if (item.getValue()==id) {
                    right = item;
                    break;
                }
            }
            return right;
        }

    };

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "AUTHORITY_ID")
    private Long id;

    @Column(name = "RIGHT_ID")
    private int rightId;

    public Right getRight () {
        return Right.parse(this.rightId);
    }

    public void setRight(Right right) {
        this.rightId = right.getValue();
    }

}

50
তাই দুঃখজনক
জেপিএর এর

20
@ জাইম রাজি! এটা কি ভেবে পাগল যে বিকাশকারীরা কোনও এনামকে এর ক্ষেত্র / বৈশিষ্ট্যের কোনও মান বা নামের পরিবর্তে তার মান / মান হিসাবে ধরে রাখতে পারে? এগুলি উভয়ই চরম "ভঙ্গুর" এবং রিফ্যাক্টরিং-বন্ধুত্বপূর্ণ। এবং নামটি ব্যবহার করে ধরেও নেওয়া হয় যে আপনি জাভা এবং ডাটাবেস উভয় ক্ষেত্রে একই নামকরণ কনভেনশনটি ব্যবহার করছেন। উদাহরণস্বরূপ লিঙ্গ নিন। এটি ডাটাবেসে কেবল 'এম' বা 'এফ' হিসাবে সংজ্ঞায়িত হতে পারে তবে জেন্ডারে জেন্ডার.এমএল বা জেন্ডার.এফের পরিবর্তে জেন্ডার। এমএলএল এবং জেন্ডার.ফেমেল ব্যবহার করা থেকে আমাকে বাধা দেওয়া উচিত নয়।
spaaarky21

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

2
আসলে, আমি মানটি দেখতে পাই ... আমি আমার মন্তব্যের সেই অংশটি মুছে ফেলব, যদি আমি এখনও এটি সম্পাদনা করতে পারি: P: D
Svend Hansen

13
জেপিএ 2.1 এর স্থানীয়ভাবে রূপান্তরকারী সমর্থন থাকবে। দয়া করে কিছু যদিওটসনজভা.ব্লগস্পট.ফি.সি.
২০১৩ /

69

এটি এখন জেপিএ ২.১ এর মাধ্যমে সম্ভব:

@Column(name = "RIGHT")
@Enumerated(EnumType.STRING)
private Right right;

অধিকতর বিস্তারিত:


2
এখন কি সম্ভব? অবশ্যই আমরা ব্যবহার করতে পারি @Converter, তবে enumবাক্সের বাইরে আরও মার্জিতভাবে পরিচালনা করা উচিত!
YoYo

4
"উত্তর" উল্লেখ করে 2 টি লিঙ্ক যা একটি AttributeConverterবিউটি ব্যবহারের কথা বলে এমন কিছু কোড উদ্ধৃত করে যা কোনওরকম কিছুই করে না এবং অপটির উত্তর দেয় না।

@ ডিএন 1 এটিকে উন্নত করতে নির্দ্বিধায় মনে করেন
Tvaroh

1
এটি আপনার "উত্তর", সুতরাং আপনার "এটি উন্নত করা উচিত"। ইতিমধ্যে একটি উত্তর আছেAttributeConverter

1
যুক্ত করার পরে @Convert(converter = Converter.class) @Enumerated(EnumType.STRING)
নিখুঁতভাবে

23

JPA 2.1 থেকে আপনি AttributeConverter ব্যবহার করতে পারেন ।

এর মতো একটি গণিত শ্রেণি তৈরি করুন:

public enum NodeType {

    ROOT("root-node"),
    BRANCH("branch-node"),
    LEAF("leaf-node");

    private final String code;

    private NodeType(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }
}

এবং এর মত একটি রূপান্তরকারী তৈরি করুন:

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class NodeTypeConverter implements AttributeConverter<NodeType, String> {

    @Override
    public String convertToDatabaseColumn(NodeType nodeType) {
        return nodeType.getCode();
    }

    @Override
    public NodeType convertToEntityAttribute(String dbData) {
        for (NodeType nodeType : NodeType.values()) {
            if (nodeType.getCode().equals(dbData)) {
                return nodeType;
            }
        }

        throw new IllegalArgumentException("Unknown database value:" + dbData);
    }
}

আপনার সত্তা সত্তা প্রয়োজন:

@Column(name = "node_type_code")

আপনার ভাগ্য @Converter(autoApply = true)ধারক অনুসারে পরিবর্তিত হতে পারে তবে ওয়াইল্ডফ্লাই 8.1.0 এ কাজ করার জন্য পরীক্ষিত tested যদি এটি কাজ না করে তবে আপনি @Convert(converter = NodeTypeConverter.class)সত্তা শ্রেণীর কলামে যুক্ত করতে পারেন ।


"মান ()" হ'ল "নোডটাইপ.ভ্যালু ()" হওয়া উচিত
কার্টিস ইয়ালাপ

17

সর্বোত্তম পন্থা হ'ল প্রতিটি এনাম টাইপের জন্য একটি অনন্য আইডি মানচিত্র করা, এভাবে ORDINAL এবং STRING এর ক্ষতিগুলি এড়ানো। এই পোস্টটি দেখুন যা আপনি এনামকে ম্যাপ করতে পারবেন এমন 5 টি রূপরেখা দেখায়।

উপরের লিঙ্কটি থেকে নেওয়া:

1 & 2। @ গণিত ব্যবহার করে

@ জেনারেটেড টিকাটি ব্যবহার করে আপনার জেপিএ সত্তাগুলির মধ্যে এনামগুলিকে মানচিত্র করতে পারেন এমন দুটি উপায় রয়েছে। দুর্ভাগ্যক্রমে এনামটাইপ.আরস্টিং এবং এনামটাইপ.অর্ডিনাল উভয়েরই সীমাবদ্ধতা রয়েছে।

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

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

৩. লাইফসাইকেল কলব্যাকস

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

৪. প্রতিটি এনাম টাইপের অনন্য আইডি ম্যাপিং

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

৫. জাভা EE7 @ কনভার্ট ব্যবহার করে

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

আমার পছন্দ: (সংখ্যা 4)

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

কোড উদাহরণের জন্য মূল পোস্টটি দেখুন ।


1
javax.persistance.Converter সহজ এবং @ কনভার্টারের সাথে (অটোপ্লাই = সত্য) এটি ডোমেন ক্লাসকে @ কনভার্ট টীকা মুক্ত রাখতে সক্ষম করে
রোস্টিস্লাভ ম্যাটল

9

সমস্যাটি হ'ল, আমি মনে করি, জেপিএ কখনই এই ধারণাটি ধারণ করে নি যে আমাদের ইতিমধ্যে একটি জটিল প্রিক্সিস্টিকিং স্কিমা থাকতে পারে।

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

  1. নাম () এবং অর্ডিনাল () ব্যবহারের সীমাবদ্ধতা। আমরা @ ইডিটির সাথে কেবল কীভাবে চিহ্নিত করবো না, আমরা @ ইন্টিটির সাথে যেভাবে করি?
  2. এনামের সাধারণত একটি নাম, বর্ণনামূলক নাম, স্থানীয়করণ সহ কোনও কিছু ইত্যাদির সাথে মেটাডেটার সমস্ত প্রকারের সাথে মেলামেশার জন্য ডেটাবেজে প্রতিনিধিত্ব থাকে আমাদের কোনও সত্তার নমনীয়তার সাথে মিলিয়ে একটি এনাম ব্যবহারের সহজ প্রয়োজন।

আমার কারণ এবং JPA_SPEC-47 এ ভোট দিতে সহায়তা করুন

সমস্যা সমাধানের জন্য @ কনভার্টার ব্যবহারের চেয়ে এটি কি আরও মার্জিত হবে না?

// Note: this code won't work!!
// it is just a sample of how I *would* want it to work!
@Enumerated
public enum Language {
  ENGLISH_US("en-US"),
  ENGLISH_BRITISH("en-BR"),
  FRENCH("fr"),
  FRENCH_CANADIAN("fr-CA");
  @ID
  private String code;
  @Column(name="DESCRIPTION")
  private String description;

  Language(String code) {
    this.code = code;
  }

  public String getCode() {
    return code;
  }

  public String getDescription() {
    return description;
  }
}

4

সম্ভবত পাস্কালের সম্পর্কিত কোডটি বন্ধ করুন

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

    public enum Right {
        READ(100), WRITE(200), EDITOR(300);

        private Integer value;

        private Right(Integer value) {
            this.value = value;
        }

        // Reverse lookup Right for getting a Key from it's values
        private static final Map<Integer, Right> lookup = new HashMap<Integer, Right>();
        static {
            for (Right item : Right.values())
                lookup.put(item.getValue(), item);
        }

        public Integer getValue() {
            return value;
        }

        public static Right getKey(Integer value) {
            return lookup.get(value);
        }

    };

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "AUTHORITY_ID")
    private Long id;

    @Column(name = "RIGHT_ID")
    private Integer rightId;

    public Right getRight() {
        return Right.getKey(this.rightId);
    }

    public void setRight(Right right) {
        this.rightId = right.getValue();
    }

}

3

আমি অনুসরণ করা হবে:

এর নিজস্ব ফাইলটিতে পৃথকভাবে এনাম ঘোষণা করুন:

public enum RightEnum {
      READ(100), WRITE(200), EDITOR (300);

      private int value;

      private RightEnum (int value) { this.value = value; }


      @Override
      public static Etapa valueOf(Integer value){
           for( RightEnum r : RightEnum .values() ){
              if ( r.getValue().equals(value))
                 return r;
           }
           return null;//or throw exception
     }

      public int getValue() { return value; }


}

রাইট নামে একটি নতুন জেপিএ সত্তা ঘোষণা করুন

@Entity
public class Right{
    @Id
    private Integer id;
    //FIElDS

    // constructor
    public Right(RightEnum rightEnum){
          this.id = rightEnum.getValue();
    }

    public Right getInstance(RightEnum rightEnum){
          return new Right(rightEnum);
    }


}

এই মানগুলি পাওয়ার জন্য আপনারও একটি কনভার্টারের প্রয়োজন হবে (কেবলমাত্র জেপিএ ২.১ এবং এর মধ্যে সমস্যাটি এখানে রূপান্তরকারী ব্যবহার করে সরাসরি চালিয়ে যাওয়ার জন্য আমি এই এনামদের সাথে এখানে আলোচনা করব না, সুতরাং এটি কেবল একমুখী রাস্তা হবে)

import mypackage.RightEnum;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

/**
 * 
 * 
 */
@Converter(autoApply = true)
public class RightEnumConverter implements AttributeConverter<RightEnum, Integer>{

    @Override //this method shoudn´t be used, but I implemented anyway, just in case
    public Integer convertToDatabaseColumn(RightEnum attribute) {
        return attribute.getValue();
    }

    @Override
    public RightEnum convertToEntityAttribute(Integer dbData) {
        return RightEnum.valueOf(dbData);
    }

}

কর্তৃপক্ষ সত্তা:

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {


  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "AUTHORITY_ID")
  private Long id;

  // the **Entity** to map : 
  private Right right;

  // the **Enum** to map (not to be persisted or updated) : 
  @Column(name="COLUMN1", insertable = false, updatable = false)
  @Convert(converter = RightEnumConverter.class)
  private RightEnum rightEnum;

}

এইভাবে করে, আপনি সরাসরি এনাম ফিল্ডে সেট করতে পারবেন না। তবে আপনি কর্তৃপক্ষ ব্যবহার করে সঠিক ক্ষেত্রটি সেট করতে পারেন

autorithy.setRight( Right.getInstance( RightEnum.READ ) );//for example

এবং যদি আপনার তুলনা করার প্রয়োজন হয় তবে আপনি ব্যবহার করতে পারেন:

authority.getRight().equals( RightEnum.READ ); //for example

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


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

দেখা যাক.

রাইটইনাম:

public enum RightEnum {
      READ(100), WRITE(200), EDITOR (300);

      private int value;

      private RightEnum (int value) { 
            try {
                  this.value= value;
                  final Field field = this.getClass().getSuperclass().getDeclaredField("ordinal");
                  field.setAccessible(true);
                  field.set(this, value);
             } catch (Exception e) {//or use more multicatch if you use JDK 1.7+
                  throw new RuntimeException(e);
            }
      }


      @Override
      public static Etapa valueOf(Integer value){
           for( RightEnum r : RightEnum .values() ){
              if ( r.getValue().equals(value))
                 return r;
           }
           return null;//or throw exception
     }

      public int getValue() { return value; }


}

এবং কর্তৃপক্ষ সত্তা

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {


  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "AUTHORITY_ID")
  private Long id;


  // the **Enum** to map (to be persisted or updated) : 
  @Column(name="COLUMN1")
  @Enumerated(EnumType.ORDINAL)
  private RightEnum rightEnum;

}

এই দ্বিতীয় ধারণাটিতে, আমরা অর্ডিনাল অ্যাট্রিবিউট হ্যাক করার পরে এটি একটি নিখুঁত পরিস্থিতি নয়, তবে এটি অনেক ছোট কোডিং।

আমি মনে করি যে জেপিএ স্পেসিফিকেশনটিতে এনামটাইপ.আইডি অন্তর্ভুক্ত করা উচিত যেখানে এনাম মান ক্ষেত্রটি কিছুটা @EnumId টীকা সহ এনটেট করা উচিত।


2

এই জাতীয় এনপিএম জেপিএ ম্যাপিং সমাধানের জন্য আমার নিজের সমাধানটি নিম্নলিখিত।

পদক্ষেপ 1 - নিম্নলিখিত ইন্টারফেসটি লিখুন যা আমরা সমস্ত এনামের জন্য ব্যবহার করব যা আমরা একটি ডিবি কলামে মানচিত্র করতে চাই:

public interface IDbValue<T extends java.io.Serializable> {

    T getDbVal();

}

পদক্ষেপ 2 - নিম্নলিখিত হিসাবে একটি কাস্টম জেনেরিক জেপিএ রূপান্তরকারী প্রয়োগ করুন:

import javax.persistence.AttributeConverter;

public abstract class EnumDbValueConverter<T extends java.io.Serializable, E extends Enum<E> & IDbValue<T>>
        implements AttributeConverter<E, T> {

    private final Class<E> clazz;

    public EnumDbValueConverter(Class<E> clazz){
        this.clazz = clazz;
    }

    @Override
    public T convertToDatabaseColumn(E attribute) {
        if (attribute == null) {
            return null;
        }
        return attribute.getDbVal();
    }

    @Override
    public E convertToEntityAttribute(T dbData) {
        if (dbData == null) {
            return null;
        }
        for (E e : clazz.getEnumConstants()) {
            if (dbData.equals(e.getDbVal())) {
                return e;
            }
        }
        // handle error as you prefer, for example, using slf4j:
        // log.error("Unable to convert {} to enum {}.", dbData, clazz.getCanonicalName());
        return null;
    }

}

এই শ্রেণীর enum মান রূপান্তর করবে Eধরনের একটি ডাটাবেস ক্ষেত্রের T(যেমন Stringব্যবহারের মাধ্যমে) getDbVal()enum উপর E, এবং তদ্বিপরীত।

পদক্ষেপ 3 - আসল এনামগুলিকে আমাদের প্রথম ধাপে সংজ্ঞায়িত ইন্টারফেসটি প্রয়োগ করতে দিন:

public enum Right implements IDbValue<Integer> {
    READ(100), WRITE(200), EDITOR (300);

    private final Integer dbVal;

    private Right(Integer dbVal) {
        this.dbVal = dbVal;
    }

    @Override
    public Integer getDbVal() {
        return dbVal;
    }
}

পদক্ষেপ 4 - Rightপদক্ষেপ 3 এর এনামের জন্য ধাপ 2 এর রূপান্তরকারী প্রসারিত করুন :

public class RightConverter extends EnumDbValueConverter<Integer, Right> {
    public RightConverter() {
        super(Right.class);
    }
}

পদক্ষেপ 5 - চূড়ান্ত পদক্ষেপটি হ'ল ক্ষেত্রটি নিম্নরূপে টীকায়িত করা:

@Column(name = "RIGHT")
@Convert(converter = RightConverter.class)
private Right right;

উপসংহার

যদি আপনার মানচিত্রের অনেক এনাম থাকে এবং আপনি এনামের একটি নির্দিষ্ট ক্ষেত্রকে ম্যাপিংয়ের মান হিসাবে ব্যবহার করতে চান তবে এটিই সবচেয়ে পরিষ্কার এবং সর্বাধিক মার্জিত সমাধান IM

আপনার প্রকল্পের অন্য সকল এনামদের জন্য যাদের একই ম্যাপিং যুক্তির প্রয়োজন, আপনাকে কেবল 3 থেকে 5 পদক্ষেপের পুনরাবৃত্তি করতে হবে, তা হল:

  • IDbValueআপনার এনামের ইন্টারফেসটি প্রয়োগ করুন ;
  • EnumDbValueConverterমাত্র 3 লাইন কোড সহ প্রসারিত করুন (পৃথক শ্রেণি তৈরি করা এড়াতে আপনি নিজের সত্তার মধ্যেও এটি করতে পারেন);
  • প্যাকেজ @Convertথেকে এনাম বৈশিষ্ট্যটি বর্ননা করুন javax.persistence

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


1
public enum Gender{ 
    MALE, FEMALE 
}



@Entity
@Table( name="clienti" )
public class Cliente implements Serializable {
...

// **1 case** - If database column type is number (integer) 
// (some time for better search performance)  -> we should use 
// EnumType.ORDINAL as @O.Badr noticed. e.g. inserted number will
// index of constant starting from 0... in our example for MALE - 0, FEMALE - 1.
// **Possible issue (advice)**: you have to add the new values at the end of
// your enum, in order to keep the ordinal correct for future values.

@Enumerated(EnumType.ORDINAL)
    private Gender gender;


// **2 case** - If database column type is character (varchar) 
// and you want to save it as String constant then ->

@Enumerated(EnumType.STRING)
    private Gender gender;

...
}

// in all case on code level you will interact with defined 
// type of Enum constant but in Database level

প্রথম কেস ( EnumType.ORDINAL)

╔════╦══════════════╦════════╗
 ID     NAME       GENDER 
╠════╬══════════════╬════════╣
  1  Jeff Atwood      0   
  2  Geoff Dalgas     0   
  3 Jarrod Jesica     1   
  4  Joel Lucy        1   
╚════╩══════════════╩════════╝

দ্বিতীয় কেস ( EnumType.STRING)

╔════╦══════════════╦════════╗
 ID     NAME       GENDER 
╠════╬══════════════╬════════╣
  1  Jeff Atwood    MALE  
  2  Geoff Dalgas   MALE  
  3 Jarrod Jesica  FEMALE 
  4  Joel Lucy     FEMALE 
╚════╩══════════════╩════════╝
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.