Object Relational Mapping with the Java Persistence API


Java වල Object-Relational Mapping (ORM) සහ JPA: දත්ත සමුදායන් සමඟ පහසුවෙන් වැඩ කරමු
ආයුබෝවන්! වර්තමාන Java යෙදුම් (Applications) බොහොමයකට දත්ත ගබඩා කිරීම සහ නැවත ලබා ගැනීම සඳහා සම්බන්ධතාත්මක දත්ත සමුදායන් (Relational Databases - MySQL, PostgreSQL, Oracle වැනි) සමඟ කටයුතු කිරීමට සිදුවෙනවා. Java ලෝකය පදනම් වෙන්නේ වස්තු (Objects) සහ ක්ලාස් (Classes) මත. නමුත් දත්ත සමුදායන් වැඩ කරන්නේ වගු (Tables), පේළි (Rows) සහ තීරු (Columns) සමඟ. මේ ලෝක දෙක අතර දත්ත හුවමාරු කිරීමේදී යම් නොගැලපීමක් (Object-Relational Impedance Mismatch) තියෙනවා.
සාම්ප්රදායිකව, අපි JDBC (Java Database Connectivity) API එක පාවිච්චි කරලා, SQL (Structured Query Language) විමසුම් (Queries) අතින් ලියලා, ResultSet
වලින් දත්ත අරගෙන, ඒවා Java Objects වලට අතින් map කරගන්නවා. මේක කුඩා වැඩ වලට ප්රශ්නයක් නැති වුනත්, ලොකු යෙදුම් වලදී:
repetitive, නීරස කේත ලියන්න වෙනවා (Boilerplate code).
වැරදීම් වෙන්න තියෙන ඉඩකඩ වැඩියි.
Business Logic වෙනුවට දත්ත ප්රවේශ ස්ථරය (Data Access Layer) ගැන වැඩිපුර හිතන්න වෙනවා.
භාවිතා කරන දත්ත සමුදාය මාරු කළොත්, SQL Queries ගොඩක් වෙනස් කරන්න වෙනවා.
මේ අභියෝගයට විසඳුමක් විදියට තමයි Object-Relational Mapping (ORM) සංකල්පය බිහිවුනේ.
Object-Relational Mapping (ORM) යනු කුමක්ද?
ORM කියන්නේ තාක්ෂණික ක්රමවේදයක් (technique). සරලවම කිව්වොත්, මේක Java Objects සහ Relational Database Tables අතර පාලමක් වගේ වැඩ කරනවා. ORM framework එකක් විසින්:
ඔබේ Java Objects දත්ත සමුදායේ වගු (Tables) වලට සිතියම්ගත (map) කරනවා.
Object එකක් save කරන්න කිව්වම, අදාළ SQL
INSERT
හෝUPDATE
statement එක generate කරලා execute කරනවා.Object එකක් load කරන්න කිව්වම, අදාළ SQL
SELECT
statement එක generate කරලා, එන ප්රතිඵල අරගෙන අදාළ Java object එක හදලා දෙනවා.Objects අතර තියෙන සම්බන්ධතා (Relationships - One-to-One, One-to-Many, Many-to-Many) දත්ත සමුදා මට්ටමේ සම්බන්ධතා (Foreign Keys) වලට map කරනවා.
මේක හරියට භාෂා දෙකක් අතර ඉන්න පරිවර්තකයෙක් වගේ. ඔබ Object භාෂාවෙන් කතා කරනවා, ORM එක ඒක Database භාෂාවට (SQL) පරිවර්තනය කරලා දෙනවා, Database එකෙන් එන උත්තර ආයෙත් Object භාෂාවට හරවලා දෙනවා.
ORM වල වාසි:
අඩු කේත: JDBC වල ලියන්න වෙන boilerplate code විශාල ප්රමාණයක් ඉවත් වෙනවා.
වැඩි ඵලදායිතාව: Database එක්ක වැඩ කරන එක සරල වෙන නිසා, developer ට Business Logic එක ගැන වැඩි අවධානයක් යොමු කරන්න පුළුවන්.
දත්ත සමුදා ස්වාධීනත්වය: බොහෝ දුරට, එක ORM එකකින් ලියපු කේතය, යටින් තියෙන Database එක මාරු කළත් (උදා: MySQL සිට PostgreSQL) ලොකු වෙනසක් නැතුව වැඩ කරන්න පුළුවන් (ORM එක අදාළ SQL dialect එක generate කරන නිසා).
වස්තු-නැඹුරු ප්රවේශය: Database එක්ක වුනත් Objects වලින්ම හිතලා වැඩ කරන්න පුළුවන්.
Java Persistence API (JPA) යනු කුමක්ද?
Java ලෝකයේ ORM ක්රියාත්මක වෙන්න ඕන කොහොමද කියන එකට සම්මතයක් (Standard) අවශ්ය වුනා. අන්න ඒ සම්මත පිරිවිතරය (Specification) තමයි Java Persistence API (JPA) කියන්නේ.
වැදගත්ම දේ: JPA කියන්නේ software එකක් නෙවෙයි, API එකක් (නීති රීති සහ Interfaces මාලාවක්) විතරයි.
මේ JPA Specification එක ක්රියාත්මක කරන (Implement) කරන ORM Frameworks තියෙනවා. ජනප්රියම ඒවා තමයි:
Hibernate: බහුලවම භාවිතා වන, ඉතා ප්රබල JPA implementation එකක්.
EclipseLink: JPA Reference Implementation එක (JPA හදපු අයම හදපු ආදර්ශ ක්රියාත්මක කිරීම).
OpenJPA: Apache ආයතනයේ implementation එකක්.
JPA භාවිතා කිරීමේ වාසිය: ඔබ කේත ලියන්නේ JPA Specification එකට අනුව නිසා, අවශ්ය නම් යටින් තියෙන Implementation එක (උදා: Hibernate සිට EclipseLink වලට) පහසුවෙන් මාරු කරන්න පුළුවන්කම ලැබෙනවා. ඔබේ කේතය JPA standard එකට ලියැවී ඇති නිසා ඒක provider-independent වෙනවා.
JPA හි මූලික සංකල්ප (Key Concepts)
JPA එක්ක වැඩ කරද්දී අපිට නිතර හමුවෙන දේවල් කිහිපයක් තියෙනවා:
Entity: මේ කියන්නේ Database එකේ Table එකකට map වෙන Java Class එකකට. මේ class එක
@Entity
annotation එකෙන් සලකුණු කරනවා. Table එකේ Primary Key එකට අදාළ field එක@Id
annotation එකෙන් සලකුණු කරනවා.import javax.persistence.*; @Entity // මේක Entity class එකක් බව කියනවා @Table(name="STUDENTS") // අදාළ table එකේ නම (optional, class name එකම නම්) public class Student { @Id // මේක Primary Key field එක @GeneratedValue(strategy = GenerationType.IDENTITY) // Key එක auto-generate වෙන හැටි private Long id; @Column(name="student_name", length=100) // Column එකේ නම සහ ගුණාංග private String name; private int age; // Column නම field නමම නම් @Column optional // Getters and Setters... }
Annotations: Java code එක ඇතුළේම (
@Entity
,@Table
,@Id
,@Column
,@OneToMany
,@ManyToOne
වැනි) විශේෂ සලකුණු යොදලා Mapping එක define කරනවා.EntityManager: JPA එක්ක වැඩ කරන ප්රධානම interface එක. Entities ටික manage කරන (Persistence Context එක handle කරන), Database එකත් එක්ක communicate කරන කෙනා මෙයා. Object එකක් save කරන්න (
persist
), හොයාගන්න (find
), update කරන්න (merge
), delete කරන්න (remove
), queries හදන්න (createQuery
) වගේ වැඩ වලටEntityManager
එක පාවිච්චි කරනවා.Persistence Context:
EntityManager
එක විසින් manage කරන Entity instances ටික තියාගන්න තැන. මේක පළමු මට්ටමේ cache එකක් වගේ වැඩ කරනවා. Transaction එකක් ඇතුළේදී මේ context එකේ තියෙන objects වල වෙනස්කම් track කරලා, transaction එක commit කරද්දී database එකට save කරනවා.JPQL (Java Persistence Query Language): SQL වගේම query language එකක්. හැබැයි මේක වැඩ කරන්නේ Database Tables & Columns එක්ක නෙවෙයි, Java Entities & Fields එක්ක. JPA provider එක විසින් JPQL query එක අදාළ Database එකට ගැලපෙන SQL query එකකට පරිවර්තනය කරනවා. මේක database-independent විදියට query ලියන්න උදව් වෙනවා.
// JPQL උදාහරණයක්: වයස 20ට වැඩි සියලු Students ලා සොයමු String jpql = "SELECT s FROM Student s WHERE s.age > :minAge"; TypedQuery<Student> query = entityManager.createQuery(jpql, Student.class); query.setParameter("minAge", 20); List<Student> results = query.getResultList();
(Optional) Criteria API: JPQL වගේ string විදියට query ලියන්නේ නැතුව, Java code වලින්ම, type-safe විදියට queries හදන්න තියෙන තවත් ක්රමයක්.
persistence.xml
: JPA configuration file එක. Database connection details (URL, username, password, driver), JPA provider එක (Hibernate/EclipseLink), manage කරන Entity classes මොනවද කියන එක වගේ දේවල් මේ file එකේ define කරනවා. (Spring Boot වගේ framework වලදී මේකapplication.properties
හෝapplication.yml
වලට ගන්න පුළුවන්).
සරල උදාහරණයක්: Student කෙනෙක් Save කිරීම
// EntityManagerFactory එකක් හදාගන්නවා (සාමාන්යයෙන් application එක පටන්ගද්දී)
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit-name"); // persistence.xml එකේ නම
// EntityManager එකක් හදාගන්නවා
EntityManager em = emf.createEntityManager();
try {
// Transaction එකක් පටන් ගන්නවා
em.getTransaction().begin();
// අලුත් Student object එකක් හදනවා
Student newStudent = new Student();
newStudent.setName("කමල් පෙරේරා");
newStudent.setAge(22);
// EntityManager එක හරහා object එක persist කරනවා (DB එකට save කරන්න ලෑස්ති කරනවා)
em.persist(newStudent);
// Transaction එක commit කරනවා (වෙනස්කම් DB එකට save වෙනවා)
em.getTransaction().commit();
System.out.println("ශිෂ්යයා සාර්ථකව ඇතුළත් කරන ලදී! ID: " + newStudent.getId());
} catch (Exception e) {
// Error එකක් ආවොත් transaction එක rollback කරනවා
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
e.printStackTrace();
} finally {
// EntityManager එක close කරනවා
em.close();
}
// EntityManagerFactory එක close කරනවා (application එක නවතිද්දී)
emf.close();
සැලකිය යුතු කරුණු
ORM/JPA ඉගෙනගන්න යම් කාලයක් ගතවෙනවා (Learning Curve).
ORM layer එක නිසා සමහරවිට performance ගැටළු එන්න පුළුවන් (N+1 select problem වැනි). ඒ නිසා ORM කොහොමද SQL generate කරන්නේ කියන එක ගැන යම් අවබෝධයක් සහ අවශ්ය විට performance tuning කිරීම වැදගත්.
ORM පාවිච්චි කළත්, සංකීර්ණ අවස්ථා වලදී SQL ගැන දැනුම තවමත් ප්රයෝජනවත්.
අවසාන වශයෙන්
Object-Relational Mapping (ORM) සහ Java Persistence API (JPA) කියන්නේ නූතන Java යෙදුම් වල දත්ත සමුදායන් සමඟ කටයුතු කිරීම බෙහෙවින් සරල කරන, developer ඵලදායිතාවය වැඩි කරන ඉතා වැදගත් තාක්ෂණයන්. JDBC වලින් ලියන්න වෙන කේත ප්රමාණය අඩු කර, වස්තු-නැඹුරු ආකාරයට දත්ත සමඟ වැඩ කිරීමට JPA ඉඩ සලසනවා. Spring Boot වැනි ජනප්රිය frameworks වල Spring Data JPA හරහා මෙය තවත් පහසු කර තිබෙනවා. Database එක්ක වැඩ කරන Java developer කෙනෙක්ට JPA ගැන දැනුම අත්යවශ්යම වෙනවා.
Subscribe to my newsletter
Read articles from Uthsara Basnayake directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
