জেপিএ এবং হাইবারনেটের সাথে একটি সমন্বিত কী কীভাবে মানচিত্র করবেন?


203

এই কোডটিতে, সম্মিলিত কী (হাইবারনেটে সংমিশ্রিত কী কীভাবে) জন্য জাভা শ্রেণি তৈরি করা যায়:

create table Time (
     levelStation int(15) not null,
     src varchar(100) not null,
     dst varchar(100) not null,
     distance int(15) not null,
     price int(15) not null,
     confPathID int(15) not null,
     constraint ConfPath_fk foreign key(confPathID) references ConfPath(confPathID),
     primary key (levelStation, confPathID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


1
উদাহরণগুলির সত্যই একটি ভাল সেট: vladmihalcea.com/2016/08/01/…
টেকহান্টার

উত্তর:


415

একটি যৌগিক কী মানচিত্রে, আপনি ব্যবহার করতে পারেন EmbeddedId বাIdClass টীকা নেই। আমি জানি এই প্রশ্নটি জেপিএ সম্পর্কে কঠোরভাবে নয় তবে স্পেসিফিকেশন দ্বারা নির্ধারিত নিয়মগুলিও প্রযোজ্য। সুতরাং তারা এখানে:

২.১.৪ প্রাথমিক কী এবং সত্ত্বার পরিচয়

...

একটি যৌগিক প্রাথমিক কীটি অবশ্যই একটি একক অবিচলিত ক্ষেত্র বা সম্পত্তি বা নীচে বর্ণিত যেমন ক্ষেত্র বা বৈশিষ্ট্যের সংখ্যার সাথে মিলিত হতে হবে। সম্মিলিত প্রাথমিক কী উপস্থাপনের জন্য একটি প্রাথমিক কী শ্রেণি নির্ধারণ করতে হবে। লিগ্যাসি ডাটাবেসগুলি থেকে ম্যাপিং করার সময় সম্মিলিত প্রাথমিক কীগুলি সাধারণত উত্থাপিত হয় যখন ডাটাবেস কীটি বেশ কয়েকটি কলামের সমন্বয়ে থাকে। এবং টীকা যৌগিক প্রাথমিক কী বোঝাতে ব্যবহার করা হয়। বিভাগ 9.1.14 এবং 9.1.15 দেখুন।EmbeddedIdIdClass

...

নিম্নলিখিত নিয়মগুলি সম্মিলিত প্রাথমিক কীগুলির জন্য প্রযোজ্য:

  • প্রাথমিক কী শ্রেণি অবশ্যই সর্বজনীন হতে হবে এবং অবশ্যই একটি সর্বজনীন নো-আরগ নির্মাণকারী থাকতে হবে have
  • সম্পত্তি-ভিত্তিক অ্যাক্সেস ব্যবহার করা হলে, প্রাথমিক কী শ্রেণীর বৈশিষ্ট্যগুলি অবশ্যই সর্বজনীন বা সুরক্ষিত থাকতে হবে।
  • প্রাথমিক কী শ্রেণি অবশ্যই হবে serializable
  • প্রাথমিক কী শ্রেণীর অবশ্যই সংজ্ঞা equalsএবং hashCode পদ্ধতি থাকতে হবে । এই পদ্ধতির জন্য মান সাম্যের শব্দার্থবিজ্ঞানগুলি অবশ্যই কী ম্যাপ করা হয় সেই ডাটাবেসের জন্য ডেটাবেস সমতার সাথে সামঞ্জস্যপূর্ণ হতে হবে।
  • একটি যৌগিক প্রাথমিক কীটি হয় এম্বেডযোগ্য শ্রেণীরূপে উপস্থাপন এবং ম্যাপ করা আবশ্যক (বিভাগ 9.1.14, "এম্বেডড এনডোটেশন" দেখুন) বা সত্তা শ্রেণীর একাধিক ক্ষেত্র বা বৈশিষ্ট্যে ম্যাপ করা উচিত (বিভাগ 9.1.15, "আইডক্লাস দেখুন" টীকা ")।
  • যদি সম্মিলিত প্রাথমিক কী শ্রেণীর সত্ত্বা শ্রেণীর একাধিক ক্ষেত্র বা বৈশিষ্ট্যগুলিতে ম্যাপ করা থাকে তবে প্রাথমিক কী শ্রেণীর প্রাথমিক কী ক্ষেত্র বা বৈশিষ্ট্যের নাম এবং সত্তা শ্রেণীর যাদের অবশ্যই সংশ্লিষ্ট হতে হবে এবং তাদের প্রকারগুলি অবশ্যই একই হবে।

সাথে একটি IdClass

সম্মিলিত প্রাথমিক কী এর ক্লাসটি দেখতে দেখতে (স্থির অভ্যন্তর শ্রেণি হতে পারে) হতে পারে:

public class TimePK implements Serializable {
    protected Integer levelStation;
    protected Integer confPathID;

    public TimePK() {}

    public TimePK(Integer levelStation, Integer confPathID) {
        this.levelStation = levelStation;
        this.confPathID = confPathID;
    }
    // equals, hashCode
}

এবং সত্তা:

@Entity
@IdClass(TimePK.class)
class Time implements Serializable {
    @Id
    private Integer levelStation;
    @Id
    private Integer confPathID;

    private String src;
    private String dst;
    private Integer distance;
    private Integer price;

    // getters, setters
}

IdClassটীকা টেবিল পি কে একাধিক ক্ষেত্র মানচিত্র তৈরী করে।

সঙ্গে EmbeddedId

সম্মিলিত প্রাথমিক কী এর ক্লাসটি দেখতে দেখতে (স্থির অভ্যন্তর শ্রেণি হতে পারে) হতে পারে:

@Embeddable
public class TimePK implements Serializable {
    protected Integer levelStation;
    protected Integer confPathID;

    public TimePK() {}

    public TimePK(Integer levelStation, Integer confPathID) {
        this.levelStation = levelStation;
        this.confPathID = confPathID;
    }
    // equals, hashCode
}

এবং সত্তা:

@Entity
class Time implements Serializable {
    @EmbeddedId
    private TimePK timePK;

    private String src;
    private String dst;
    private Integer distance;
    private Integer price;

    //...
}

@EmbeddedIdটীকা টেবিল পি কে একটি পি কে বর্গ মানচিত্র তৈরী করে।

পার্থক্য:

  • শারীরিক মডেল দৃষ্টিকোণ থেকে, কোনও পার্থক্য নেই
  • @EmbeddedIdকোনওরকমভাবে আরও স্পষ্টভাবে যোগাযোগ করা হয়েছে যে কীটি একটি যৌগিক কী এবং আইএমও যখন তা বোঝায় তখন যখন সম্মিলিত পিকে নিজেই কোনও অর্থবহ সত্তা হয় বা এটি আপনার কোডে পুনরায় ব্যবহার করা হয়
  • @IdClass উল্লেখ করার যে ক্ষেত্র কিছু সমন্বয় অনন্য কিন্তু এই একটি বিশেষ অর্থ আছে না হয়

আপনার প্রশ্নগুলি লেখার পদ্ধতিতেও এগুলি প্রভাবিত করে (এগুলিকে কমবেশি শব্দ বানানো):

  • সঙ্গে IdClass

    select t.levelStation from Time t
  • সঙ্গে EmbeddedId

    select t.timePK.levelStation from Time t

তথ্যসূত্র

  • জেপিএ 1.0 স্পেসিফিকেশন
    • বিভাগ 2.1.4 "প্রাথমিক কী এবং সত্ত্বার পরিচয়"
    • বিভাগ 9.1.14 "এম্বেডডড এনডোটেশন"
    • বিভাগ 9.1.15 "আইডক্লাস টিকা"

15
একটি হাইবারনেট-নির্দিষ্ট সমাধান রয়েছে: বহিরাগত শ্রেণিকে সনাক্তকারী প্রকার হিসাবে ঘোষণা না করে @ আইড বৈশিষ্ট্য হিসাবে একাধিক বৈশিষ্ট্য মানচিত্র করুন (এবং আইডক্লাস টিকাটি ব্যবহার করুন)। 5.1.2.1 দেখুন হাইবারনেট ম্যানুয়ালটিতে যৌগিক শনাক্তকারী
জোহান বোবার্গ

আপনি কি এই প্রশ্নটি একবার দেখে নিতে পারেন ? সদস্য ক্ষেত্রটি idসর্বদা থাকে nullএবং উত্পন্ন হয় না বলে আমি একটি যৌগিক প্রাথমিক কী নিয়ে সমস্যায়
পড়ছি

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

যদিও হাইবারনেট নির্দিষ্ট সমাধানটি হ্রাস করা হয়।
নিখিল সাহু

থেকে হাইবারনেট টীকা ডক্স , সম্পর্কে @IdClass: "এটি অনগ্রসর compatibilities জন্য EJB 2 অন্ধকার বয়সের থেকে উত্তরাধিকারসূত্রে করা হয়েছে এবং আমরা তা (সরলতা অনুরোধে জন্য) ব্যবহার না করার পরামর্শ দিই।"
মার্কো ফেরারি

49

আপনার ব্যবহার করা দরকার @EmbeddedId:

@Entity
class Time {
    @EmbeddedId
    TimeId id;

    String src;
    String dst;
    Integer distance;
    Integer price;
}

@Embeddable
class TimeId implements Serializable {
    Integer levelStation;
    Integer confPathID;
}

@ থিয়েরি-দিমিত্রি রয় কীভাবে আমি টাইমআইড.লেভেলস্টেশন এবং টাইম আইডি কোডফ্যাথআইডি নির্ধারণ করতে পারি। আপনি একটি উদাহরণ প্রদান করতে পারেন দয়া করে?
ডাচ ট্রান

@ থিয়েরি-দিমিত্রিরোয় প্রাথমিক শ্রেণি কি সত্তা শ্রেণির স্থির অভ্যন্তর শ্রেণি হতে পারে না?
নিখিল সাহু

হ্যাঁ, এটি হতে পারে
সামি ওমর

17

যেমনটি আমি এই নিবন্ধে ব্যাখ্যা করেছি , ধরে নিলাম আপনার নিম্নলিখিত ডাটাবেস সারণি রয়েছে:

এখানে চিত্র বর্ণনা লিখুন

প্রথমত, আপনাকে @Embeddableসম্মিলিত শনাক্তকারীটি তৈরি করতে হবে :

@Embeddable
public class EmployeeId implements Serializable {

    @Column(name = "company_id")
    private Long companyId;

    @Column(name = "employee_number")
    private Long employeeNumber;

    public EmployeeId() {
    }

    public EmployeeId(Long companyId, Long employeeId) {
        this.companyId = companyId;
        this.employeeNumber = employeeId;
    }

    public Long getCompanyId() {
        return companyId;
    }

    public Long getEmployeeNumber() {
        return employeeNumber;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof EmployeeId)) return false;
        EmployeeId that = (EmployeeId) o;
        return Objects.equals(getCompanyId(), that.getCompanyId()) &&
                Objects.equals(getEmployeeNumber(), that.getEmployeeNumber());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getCompanyId(), getEmployeeNumber());
    }
}

এটি জায়গায় রেখে, আমরা সারণিটি ম্যাপ করতে পারি Employeeযা সংযোজন শনাক্তকারী ব্যবহার করে এটির সাথে এটি বর্ণনা করে @EmbeddedId:

@Entity(name = "Employee")
@Table(name = "employee")
public class Employee {

    @EmbeddedId
    private EmployeeId id;

    private String name;

    public EmployeeId getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

Phoneসত্তা যা হয়েছে @ManyToOneথেকে সমিতি Employee, দুই মাধ্যমে পিতা বা মাতা ক্লাস থেকে যৌগিক আইডেন্টিফায়ার রেফারেন্স দরকার @JoinColumnম্যাপিং:

@Entity(name = "Phone")
@Table(name = "phone")
public class Phone {

    @Id
    @Column(name = "`number`")
    private String number;

    @ManyToOne
    @JoinColumns({
        @JoinColumn(
            name = "company_id",
            referencedColumnName = "company_id"),
        @JoinColumn(
            name = "employee_number",
            referencedColumnName = "employee_number")
    })
    private Employee employee;

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}

আরও তথ্যের জন্য, এই নিবন্ধটি দেখুন


ডিবি স্কিমা থেকে এমপ্লয়িআইডি তৈরি করতে পারে এমন কোনও সরঞ্জাম আছে?
লিওন

হাইবারনেট সরঞ্জাম ব্যবহার করে দেখুন। এটির জন্য এটির বিপরীত প্রকৌশল সরঞ্জাম রয়েছে।
ভ্লাদ মিহলসিয়া

7

প্রাথমিক কী শ্রেণীর অবশ্যই সমান এবং হ্যাশকোড পদ্ধতি নির্ধারণ করতে হবে

  1. সমানগুলি প্রয়োগ করার সময় আপনার সাবক্লাসগুলির সাথে তুলনা করার অনুমতি দেওয়ার জন্য উদাহরণ ব্যবহার করা উচিত । হাইবারনেট অলস যদি একের মধ্যে এক বা একের সাথে অনেকের বোঝা চাপায় তবে আপনার কাছে সমতল শ্রেণীর পরিবর্তে ক্লাসের জন্য একটি প্রক্সি থাকবে। একটি প্রক্সি একটি সাবক্লাস হয়। শ্রেণীর নামের সাথে তুলনা করা ব্যর্থ হবে।
    আরও প্রযুক্তিগতভাবে: আপনার লিসকোস সাবস্টিটিউশন নীতি অনুসরণ করা উচিত এবং প্রতিসাম্যতা উপেক্ষা করা উচিত।
  2. পরবর্তী সমস্যাটি নাম.ইকভালস (that.getName ()) এর পরিবর্তে name.equals (that.name) এর মতো কিছু ব্যবহার করছে । প্রথমটি ব্যর্থ হবে, যদি এটি প্রক্সি হয়।

http://www.laliluna.de/jpa-hibernate-guide/ch06s06.html


6

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


5

আসুন একটি সহজ উদাহরণ গ্রহণ করা যাক। আসুন আমরা দুটি টেবিলের নাম বলি testএবং customerসেখানে বর্ণিত আছে:

create table test(
  test_id int(11) not null auto_increment,
  primary key(test_id));

create table customer(
  customer_id int(11) not null auto_increment,
  name varchar(50) not null,
  primary key(customer_id));

আরও একটি টেবিল রয়েছে যা এর ট্র্যাক রাখে testএবং customer:

create table tests_purchased(
  customer_id int(11) not null,
  test_id int(11) not null,
  created_date datetime not null,
  primary key(customer_id, test_id));

আমরা দেখতে পাচ্ছি যে টেবিলে tests_purchasedপ্রাথমিক কীটি একটি যৌগিক কী, তাই আমরা ম্যাপিং ফাইলটিতে <composite-id ...>...</composite-id>ট্যাগটি ব্যবহার করব hbm.xml। সুতরাং PurchasedTest.hbm.xmlচেহারা দেখতে হবে:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="entities.PurchasedTest" table="tests_purchased">

    <composite-id name="purchasedTestId">
      <key-property name="testId" column="TEST_ID" />
      <key-property name="customerId" column="CUSTOMER_ID" />
    </composite-id>

    <property name="purchaseDate" type="timestamp">
      <column name="created_date" />
    </property>

  </class>
</hibernate-mapping>

তবে এখানেই শেষ হচ্ছে না। হাইবারনেটে আমরা প্রাথমিক কী ব্যবহার করে সত্তা খুঁজে পেতে এবং লোড করতে সেশন.লোড ( entityClass, id_type_object) ব্যবহার করি। সংমিশ্রিত কীগুলির ক্ষেত্রে, আইডি অবজেক্টটি পৃথক আইডি শ্রেণি হওয়া উচিত (উপরের ক্ষেত্রে কোনও PurchasedTestIdশ্রেণি) যা নীচের মতো প্রাথমিক কী বৈশিষ্ট্যগুলি ঘোষনা করে :

import java.io.Serializable;

public class PurchasedTestId implements Serializable {
  private Long testId;
  private Long customerId;

  // an easy initializing constructor
  public PurchasedTestId(Long testId, Long customerId) {
    this.testId = testId;
    this.customerId = customerId;
  }

  public Long getTestId() {
    return testId;
  }

  public void setTestId(Long testId) {
    this.testId = testId;
  }

  public Long getCustomerId() {
    return customerId;
  }

  public void setCustomerId(Long customerId) {
    this.customerId = customerId;
  }

  @Override
  public boolean equals(Object arg0) {
    if(arg0 == null) return false;
    if(!(arg0 instanceof PurchasedTestId)) return false;
    PurchasedTestId arg1 = (PurchasedTestId) arg0;
    return (this.testId.longValue() == arg1.getTestId().longValue()) &&
           (this.customerId.longValue() == arg1.getCustomerId().longValue());
  }

  @Override
  public int hashCode() {
    int hsCode;
    hsCode = testId.hashCode();
    hsCode = 19 * hsCode+ customerId.hashCode();
    return hsCode;
  }
}

গুরুত্বপূর্ণ পয়েন্ট যে আমরা দুটি ফাংশন বাস্তবায়ন হয় hashCode()এবং equals()যেমন হাইবারনেট তাদের উপর নির্ভর করে।


2

আর একটি বিকল্প মানচিত্র হ'ল কনফপ্যাথ টেবিলের সম্মিলিত উপাদানের মানচিত্র হিসাবে।

এই ম্যাপিংটি (কনফ্যাথপিডআইডি, লেভেলস্টেশন) এর সূচক থেকে উপকৃত হবে।

public class ConfPath {
    private Map<Long,Time> timeForLevelStation = new HashMap<Long,Time>();

    public Time getTime(long levelStation) {
        return timeForLevelStation.get(levelStation);
    }

    public void putTime(long levelStation, Time newValue) {
        timeForLevelStation.put(levelStation, newValue);
    }
}

public class Time {
    String src;
    String dst;
    long distance;
    long price;

    public long getDistance() {
        return distance;
    }

    public void setDistance(long distance) {
        this.distance = distance;
    }

    public String getDst() {
        return dst;
    }

    public void setDst(String dst) {
        this.dst = dst;
    }

    public long getPrice() {
        return price;
    }

    public void setPrice(long price) {
        this.price = price;
    }

    public String getSrc() {
        return src;
    }

    public void setSrc(String src) {
        this.src = src;
    }
}

ম্যাপিং:

<class name="ConfPath" table="ConfPath">
    <id column="ID" name="id">
        <generator class="native"/>
    </id>
    <map cascade="all-delete-orphan" name="values" table="example"
            lazy="extra">
        <key column="ConfPathID"/>
        <map-key type="long" column="levelStation"/>
        <composite-element class="Time">
            <property name="src" column="src" type="string" length="100"/>
            <property name="dst" column="dst" type="string" length="100"/>
            <property name="distance" column="distance"/>
            <property name="price" column="price"/>
        </composite-element>
    </map>
</class>

1

Hbm.xML ব্যবহার করে

    <composite-id>

        <!--<key-many-to-one name="productId" class="databaselayer.users.UserDB" column="user_name"/>-->
        <key-property name="productId" column="PRODUCT_Product_ID" type="int"/>
        <key-property name="categoryId" column="categories_id" type="int" />
    </composite-id>  

টীকাগুলি ব্যবহার করা হচ্ছে

সমন্বিত কী ক্লাস

public  class PK implements Serializable{
    private int PRODUCT_Product_ID ;    
    private int categories_id ;

    public PK(int productId, int categoryId) {
        this.PRODUCT_Product_ID = productId;
        this.categories_id = categoryId;
    }

    public int getPRODUCT_Product_ID() {
        return PRODUCT_Product_ID;
    }

    public void setPRODUCT_Product_ID(int PRODUCT_Product_ID) {
        this.PRODUCT_Product_ID = PRODUCT_Product_ID;
    }

    public int getCategories_id() {
        return categories_id;
    }

    public void setCategories_id(int categories_id) {
        this.categories_id = categories_id;
    }

    private PK() { }

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }

        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }

        PK pk = (PK) o;
        return Objects.equals(PRODUCT_Product_ID, pk.PRODUCT_Product_ID ) &&
                Objects.equals(categories_id, pk.categories_id );
    }

    @Override
    public int hashCode() {
        return Objects.hash(PRODUCT_Product_ID, categories_id );
    }
}

সত্তা ক্লাস

@Entity(name = "product_category")
@IdClass( PK.class )
public  class ProductCategory implements Serializable {
    @Id    
    private int PRODUCT_Product_ID ;   

    @Id 
    private int categories_id ;

    public ProductCategory(int productId, int categoryId) {
        this.PRODUCT_Product_ID = productId ;
        this.categories_id = categoryId;
    }

    public ProductCategory() { }

    public int getPRODUCT_Product_ID() {
        return PRODUCT_Product_ID;
    }

    public void setPRODUCT_Product_ID(int PRODUCT_Product_ID) {
        this.PRODUCT_Product_ID = PRODUCT_Product_ID;
    }

    public int getCategories_id() {
        return categories_id;
    }

    public void setCategories_id(int categories_id) {
        this.categories_id = categories_id;
    }

    public void setId(PK id) {
        this.PRODUCT_Product_ID = id.getPRODUCT_Product_ID();
        this.categories_id = id.getCategories_id();
    }

    public PK getId() {
        return new PK(
            PRODUCT_Product_ID,
            categories_id
        );
    }    
}

1
এটি বোঝা যায় না, তাঁর প্রাথমিক কীটি দরকার
মজেন এম্বেবি

শিরোনামে তিনি বলেছেন যৌগিক কী, যা প্রাথমিক হতে হবে না
এনারসিসিও

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