मैं जानना चाहता हूं कि EclipseLink के साथ जेपीए 2 में temporal tables को कैसे कार्यान्वित किया जाए। अस्थायी रूप से मेरा मतलब सारणी है जो वैधता अवधि को परिभाषित करती है।जेपीए का उपयोग कर एक अस्थायी तालिका को कैसे कार्यान्वित करें?
मुझे एक समस्या का सामना करना पड़ रहा है कि रेफरेंसिंग टेबलों में संदर्भित सारणी की प्रकृति की वजह से संदर्भित तालिकाओं (टेम्पोरल टेबल) में विदेशी कुंजी बाधाएं नहीं हो सकती हैं, जो अब उनकी प्राथमिक कुंजी में वैधता अवधि शामिल है।
- मैं अपनी संस्थाओं के रिश्तों को कैसे मैप करूं?
- क्या इसका मतलब यह होगा कि मेरी संस्थाओं के पास उन वैध समय इकाइयों के साथ कोई रिश्ता नहीं हो सकता है?
- क्या उन रिश्तों को शुरू करने की उत्तरदायित्व अब मेरे द्वारा किसी प्रकार की सेवा या विशेष डीएओ में मैन्युअल रूप से करनी चाहिए?
मुझे मिली एकमात्र चीज है जो DAO Fusion नामक एक ढांचा है जो इससे संबंधित है।
- क्या इसे हल करने के कोई अन्य तरीके हैं?
- क्या आप इस विषय के बारे में एक उदाहरण या संसाधन प्रदान कर सकते हैं (अस्थायी डेटाबेस के साथ जेपीए)?
यहां डेटा मॉडल और इसकी कक्षाओं का एक काल्पनिक उदाहरण है।
1 परिदृश्य:: गैर टेम्पोरल मॉडल
डेटा मॉडल:
टीम:
यह एक सरल मॉडल लौकिक पहलुओं से निपटने के लिए यह नहीं है कि के रूप में शुरू होता है@Entity
public class Team implements Serializable {
private Long id;
private String name;
private Integer wins = 0;
private Integer losses = 0;
private Integer draws = 0;
private List<Player> players = new ArrayList<Player>();
public Team() {
}
public Team(String name) {
this.name = name;
}
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQTEAMID")
@SequenceGenerator(name="SEQTEAMID", sequenceName="SEQTEAMID", allocationSize=1)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(unique=true, nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getWins() {
return wins;
}
public void setWins(Integer wins) {
this.wins = wins;
}
public Integer getLosses() {
return losses;
}
public void setLosses(Integer losses) {
this.losses = losses;
}
public Integer getDraws() {
return draws;
}
public void setDraws(Integer draws) {
this.draws = draws;
}
@OneToMany(mappedBy="team", cascade=CascadeType.ALL)
public List<Player> getPlayers() {
return players;
}
public void setPlayers(List<Player> players) {
this.players = players;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Team other = (Team) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
प्लेयर:
@Entity
@Table(uniqueConstraints={@UniqueConstraint(columnNames={"team_id","number"})})
public class Player implements Serializable {
private Long id;
private Team team;
private Integer number;
private String name;
public Player() {
}
public Player(Team team, Integer number) {
this.team = team;
this.number = number;
}
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQPLAYERID")
@SequenceGenerator(name="SEQPLAYERID", sequenceName="SEQPLAYERID", allocationSize=1)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@ManyToOne
@JoinColumn(nullable=false)
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
@Column(nullable=false)
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
@Column(unique=true, nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((number == null) ? 0 : number.hashCode());
result = prime * result + ((team == null) ? 0 : team.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Player other = (Player) obj;
if (number == null) {
if (other.number != null)
return false;
} else if (!number.equals(other.number))
return false;
if (team == null) {
if (other.team != null)
return false;
} else if (!team.equals(other.team))
return false;
return true;
}
}
टेस्ट वर्ग:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/META-INF/application-context-root.xml"})
@Transactional
public class TestingDao {
@PersistenceContext
private EntityManager entityManager;
private Team team;
@Before
public void setUp() {
team = new Team();
team.setName("The Goods");
team.setLosses(0);
team.setWins(0);
team.setDraws(0);
Player player = new Player();
player.setTeam(team);
player.setNumber(1);
player.setName("Alfredo");
team.getPlayers().add(player);
player = new Player();
player.setTeam(team);
player.setNumber(2);
player.setName("Jorge");
team.getPlayers().add(player);
entityManager.persist(team);
entityManager.flush();
}
@Test
public void testPersistence() {
String strQuery = "select t from Team t where t.name = :name";
TypedQuery<Team> query = entityManager.createQuery(strQuery, Team.class);
query.setParameter("name", team.getName());
Team persistedTeam = query.getSingleResult();
assertEquals(2, persistedTeam.getPlayers().size());
//Change the player number
Player p = null;
for (Player player : persistedTeam.getPlayers()) {
if (player.getName().equals("Alfredo")) {
p = player;
break;
}
}
p.setNumber(10);
}
}
अब आप की कैसे टीम और खिलाड़ी तो तुम क्या करने की जरूरत समय की निश्चित बिंदु पर था एक इतिहास रखने के लिए कहा जाता है जोड़ने के लिए है प्रत्येक तालिका के लिए एक अवधि का समय जो ट्रैक करना चाहता है। तो चलिए इन अस्थायी कॉलम जोड़ें। हम सिर्फ Player
के साथ शुरू करने जा रहे हैं।
2 परिदृश्य: टेम्पोरल मॉडल
डेटा मॉडल:
आप देख सकते हैं हम प्राथमिक कुंजी ड्रॉप और एक और एक है कि दिनांक (अवधि) भी शामिल है परिभाषित करने के लिए किया था। इसके अलावा हमें अनूठी बाधाओं को छोड़ना पड़ा क्योंकि अब उन्हें मेज में दोहराया जा सकता है। अब तालिका में मौजूदा प्रविष्टियां और इतिहास भी हो सकता है।
चीजें बहुत बदसूरत हो जाती हैं अगर हमें टीम अस्थायी बनाना पड़ता है, तो इस मामले में हमें विदेशी कुंजी बाधा को छोड़ना होगा कि Player
तालिका Team
है। समस्या यह है कि आप जावा और जेपीए में इसे कैसे मॉडल करेंगे।
ध्यान दें कि आईडी एक सरोगेट कुंजी है। लेकिन अब सरोगेट कुंजियों को तारीख शामिल करनी है क्योंकि यदि वे ऐसा नहीं करते हैं तो यह एक ही इकाई (टाइमलाइन के दौरान) एक से अधिक "संस्करण" स्टोर करने की अनुमति नहीं देगा।
1) आपने किस टूल के साथ चित्र खींचा? 2) एक अस्थायी आयाम आपकी आवश्यकताओं के लिए पर्याप्त है, डीओओफ़्यूजन पैटर्न और मेरा उत्तर (इन पैटर्नों के आधार पर) मेरी राय 3 में अधिक है) क्या आप ऐसे समाधान को प्राथमिकता देते हैं जो प्लेयर को अस्थायी पहलू जोड़ता है या आप पसंद करते हैं यह दोनों टेबल 4) आपका अंतिम अनुच्छेद गलत है। एक सरोगेट कुंजी में कभी भी अतिरिक्त फ़ील्ड शामिल नहीं होंगे। उस स्थिति में आपके पास दो सरोगेट कुंजी होगी। – ChrLipp
@ChrLipp 1) स्पार्क्स एंटरप्राइज़ आर्किटेक्ट 2) मैं सहमत हूं। 3) मुझे एक समाधान की आवश्यकता है जो दोनों तालिकाओं में अस्थायी जोड़ता है। 4) मैं सहमत नहीं हूं कि एक सरोगेट कुंजी नहीं है। मुझे लगता है कि यह एक सरोगेट कुंजी है क्योंकि: 1. अस्थायी कॉलम जोड़ने से पहले यह एक सरोगेट कुंजी थी जो व्यावसायिक अर्थ के साथ एक कुंजी नहीं थी।उदाहरण के लिए प्लेयर की व्यावसायिक कुंजी "team_id" और "संख्या" है और टीम से "नाम" है। दोनों में अपनी खुद की सरोगेट कुंजी "आईडी" होती है जब उनके पास अस्थायी कॉलम नहीं होते थे। समस्या यह है कि जब मैं अस्थायी कॉलम जोड़ता हूं जो अब काम नहीं करता है। एक ही प्रविष्टि एक ही तालिका में एक से अधिक बार प्रकट हो सकती है। –
यही कारण है कि सरोगेट कुंजी "आईडी" अब केवल एक कॉलम नहीं हो सकती है क्योंकि यह एक ही प्रविष्टि है लेकिन विभिन्न समय-सारिणी में ट्रैक की जाती है, ताकि एक ही प्रविष्टि को एक से अधिक बार प्रदर्शित करने की अनुमति दी जा सके। एक प्राथमिक कुंजी "आईडी + वैधता" या "आईडी + मान्य" या "आईडी + वैध प्रारंभ + वैध" के रूप में निम्नलिखित। मैंने जावा मैपिंग्स पर सुविधा के लिए आखिरी विकल्प चुना है, जहां मेरे पास एक "अंतराल" ऑब्जेक्ट है जो एक अवधि को परिभाषित करता है, इसलिए जेपीए में इसे मैप करने के लिए मैंने आईडी को "अंतराल" को एम्बेडेड आईडी के रूप में जोड़ा। –