CodeGym /Java Blog /Random /Ang iyong unang Hibernate application
John Squirrels
Antas
San Francisco

Ang iyong unang Hibernate application

Nai-publish sa grupo
Sa artikulong ito, magiging pamilyar ka sa isa sa pinakasikat na enterprise frameworks para sa Java at gagawa ng iyong unang Hibernate application. Hindi kailanman narinig ang tungkol sa Hibernate? O baka narinig mo na ito, ngunit hindi mo pa ito ginagamit? O baka sinubukan mong gamitin ito, ngunit nabigo? Sa lahat ng tatlong kaso - maligayang pagdating sa below the cut :) Ang iyong unang Hibernate application - 1 Hello, everyone! Sa artikulong ito, pag-uusapan ko ang mga pangunahing tampok ng Hibernate framework at tutulungan kang isulat ang iyong unang mini-application. Para dito, kailangan namin:
  1. IntelliJ IDEA Ultimate Edition
    I-download ito mula sa opisyal na website at i-activate ang 30-araw na trial na bersyon.
  2. PostgreSQL - isa sa pinakasikat na modernong database management system (DBMS)
  3. Maven (naka-wire na sa IDEA)
  4. Kaunting pasensya.
Kung sakali, nai-post ko ang code ng aplikasyon sa GitHub (codegym branch). Ang artikulo ay pangunahing naglalayong sa mga hindi pa nakatrabaho sa teknolohiyang ito dati, kaya pinaliit ko ang dami ng code. Magsimula na tayo!

Ano ang Hibernate?

Isa ito sa pinakasikat na pagpapatupad ng object-relational mapping (ORM). Tinutukoy ng object-relational mapping ang kaugnayan sa pagitan ng mga object ng software at mga record ng database. Siyempre, ang Hibernate ay may napakalawak na pag-andar, ngunit kami ay tumutuon sa pinakasimpleng mga pag-andar. Ang aming layunin ay lumikha ng isang CRUD (Gumawa, Magbasa, Mag-update, Magtanggal) na application na magagawang:
  1. Lumikha ng mga user (User), hanapin sila sa database sa pamamagitan ng ID, i-update ang kanilang data sa database, at tanggalin sila mula sa database.
  2. Magtalaga ng mga bagay sa kotse (Auto) sa mga user. Gumawa, mag-update, maghanap, at magtanggal ng mga kotse mula sa database.
  3. Bukod pa rito, dapat na awtomatikong alisin ng application ang mga "walang nagmamay-ari" na mga kotse mula sa database. Sa madaling salita, kapag ang isang user ay tinanggal, ang lahat ng mga kotse na pagmamay-ari ng user na iyon ay dapat ding tanggalin mula sa database.
Ang aming proyekto ay gagawing ganito: Ang iyong unang Hibernate application - 2Gaya ng nakikita mo, walang kumplikado. 6 na klase + 1 file na may mga config. Una, lumikha ng bagong proyekto ng Maven sa IntelliJ IDEA. File -> Bagong Proyekto. Piliin ang Maven mula sa mga iminungkahing uri ng proyekto at lumipat sa susunod na hakbang. Ang iyong unang Hibernate application - 3Ang Apache Maven ay isang balangkas para sa awtomatikong pagbuo ng mga proyekto batay sa isang paglalarawan ng kanilang istraktura sa mga file ng POM. Ang buong istraktura ng iyong proyekto ay ilalarawan sa pom.xml, isang file na gagawin mismo ng IDEA sa ugat ng iyong proyekto. Sa mga setting ng proyekto, kailangan mong tukuyin ang mga sumusunod na setting ng Maven: groupId at artifactId. Sa mga proyekto, ang groupId ay karaniwang isang paglalarawan ng kumpanya o yunit ng negosyo. Maaaring pumunta dito ang domain name ng kumpanya o website. Sa turn, artifactId ang pangalan ng proyekto. Para sa groupdId, maaari mong ilagay ang com.yourNickname.codegym. Hindi ito magkakaroon ng anumang epekto sa application. Para sa artifactId, pumili ng anumang pangalan ng proyekto na gusto mo. Ang bersyon ay maaaring iwanang hindi nagbabago. Ang iyong unang Hibernate application - 4Sa huling screen, kumpirmahin lang ang naunang inilagay na data.Ang iyong unang Hibernate application - 5Kaya, ginawa namin ang proyekto. Ngayon ang natitira pang gawin ay magsulat ng ilang code at gawin itong gumana :) Una muna: kung gusto naming lumikha ng isang application na gumagana sa isang database, tiyak na hindi namin magagawa nang walang database! I-download ang PostgreSQL mula dito (Gumagamit ako ng bersyon 9). Ang PostgreSQL ay may default na user na 'postgres' — kakailanganin mong mag-isip ng password para dito kapag nag-install ka. Huwag kalimutan ang password. Kakailanganin natin ito mamaya! (Sa pangkalahatan, ang paggamit ng default na database sa mga application ay masamang kasanayan, ngunit gagawin namin ito upang mabawasan ang bilang ng mga sanhi ng ulcer sa pamamagitan ng paglikha ng iyong sariling database). Kung hindi ka kaibigan sa command line at SQL query, may magandang balita. Ang IntelliJ IDEA ay nagbibigay ng ganap na angkop na user interface para sa pagtatrabaho sa database. Ang iyong unang Hibernate application - 6(matatagpuan sa kanang pane ng IDEA, ang tab na Database). Upang gumawa ng koneksyon, i-click ang "+" at piliin ang aming data source (PostgeSQL). Punan ang mga field para sa user at database ("postgres" para sa kanilang dalawa) at ilagay ang password na itinakda sa panahon ng pag-install ng PostgreSQL. Kung kinakailangan, i-download ang driver ng Postgres. Magagawa mo ito sa parehong pahina. I-click ang "Subukan ang Koneksyon" upang i-verify na ang koneksyon sa database ay naitatag. Kung nakita mo ang "Tagumpay", pagkatapos ay magpatuloy. Ngayon gagawa kami ng mga talahanayan na kailangan namin. Magkakaroon ng kabuuang dalawa: mga user at mga sasakyan. Mga parameter para sa talahanayan ng mga user: Ang iyong unang Hibernate application - 7Tandaan na ang id ang pangunahing key. Kung hindi mo alam kung ano ang pangunahing key sa SQL, i-Google ito. Ito ay mahalaga. Mga setting para sa autos table: Ang iyong unang Hibernate application - 8Para sa autos table, kailangan mong mag-configure ng foreign key. Ito ay magsisilbing link sa aming mga talahanayan. Inirerekomenda ko na magbasa ka pa tungkol dito. Sa madaling salita, ito ay tumutukoy sa isang panlabas na talahanayan, sa aming kaso, mga gumagamit. Kung ang isang kotse ay pagmamay-ari ng user na may id = 1, ang user_id field ng mga sasakyan ay magiging katumbas ng 1. Ito ay kung paano namin iniuugnay ang mga user sa kanilang mga sasakyan sa aming application. Sa aming talahanayan ng autos, ang field ng user_id ay magsisilbing foreign key. Magre-refer ito sa field ng id ng talahanayan ng mga user. Ang iyong unang Hibernate application - 9Kaya, gumawa kami ng database na may dalawang talahanayan. Ano ang natitira ay upang maunawaan kung paano pamahalaan ito mula sa Java code. Magsisimula tayo sa pom.xml file, kung saan kailangan nating isama ang mga kinakailangang aklatan (sa Maven ay tinatawag silang mga dependency). Ang lahat ng mga aklatan ay naka-imbak sa central Maven repository. Ang mga aklatan na iyong tinukoy sa pom.xml ay magagamit mo sa proyekto. Dapat ganito ang hitsura ng iyong pom.xml: Ang iyong unang Hibernate application - 10Walang kumplikado, gaya ng nakikita mo. Nagdagdag lang kami ng 2 dependency — para sa paggamit ng PostgreSQL at Hibernate. Ngayon ay lumipat tayo sa Java code. Lumikha ng lahat ng kinakailangang mga pakete at klase sa proyekto. Upang magsimula, kailangan namin ng isang modelo ng data: ang Userat Automga klase.

 package models;
 
 import javax.persistence.*;
 import java.util.ArrayList;
 import java.util.List;
 
 @Entity
 @Table (name = "users")
 public class User {
 
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private int id;
     @Column(name = "name")
     private String name;
     // You can omit the Column attribute if the name property matches the column name in the table
     private int age;
 
     @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
     private List<Auto> autos;
 
     public User() {
     }
 
     public User(String name, int age) {
         this.name = name;
         this.age = age;
         autos = new ArrayList<>();
     }
 
     public void addAuto(Auto auto) {
         auto.setUser(this);
         autos.add(auto);
     }
 
     public void removeAuto(Auto auto) {
         autos.remove(auto);
     }
 
     public int getId() {
         return id;
     }
 
     public String getName() {
         return name;
     }
 
     public void setName(String name) {
         this.name = name;
     }
 
     public int getAge() {
         return age;
     }
 
     public void setAge(int age) {
         this.age = age;
     }
 
     public List<Auto> getAutos() {
         return autos;
     }
 
     public void setAutos(List<Auto> autos) {
         this.autos = autos;
     }
 
     @Override
     public String toString() {
         return "models.User{" +
                 "id=" + id +
                 ", name='" + name + '\'' +
                 ", age=" + age +
                 '}';
     }
 }
 
 

 package models;
 
 import javax.persistence.*;
 
 @Entity
 @Table(name = "autos")
 public class Auto {
 
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private int id;
 
     @Column (name = "model")
     private String model;
 
     // You can omit the Column attribute if the name property matches the column name in the table
     private String color;
 
 
     @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "user_id")
     private User user;
 
     public Auto() {
     }
 
     public Auto(String model, String color) {
         this.model = model;
         this.color = color;
     }
 
     public int getId() {
         return id;
     }
 
     public String getModel() {
         return model;
     }
 
     public void setModel(String model) {
         this.model = model;
     }
 
     public String getColor() {
         return color;
     }
 
     public void setColor(String color) {
         this.color = color;
     }
 
     public User getUser() {
         return user;
     }
 
     public void setUser(User user) {
         this.user = user;
     }
 
     @Override
     public String toString() {
         return color + " " + model;
     }
 }
 
 
Gaya ng nakikita mo, ang mga klase ay may isang grupo ng mga hindi malinaw na anotasyon. Simulan natin ang paghuhukay sa kanila. Para sa amin, ang pangunahing anotasyon ay @Entity. Basahin ang tungkol dito sa Wikipedia at alamin ang lahat ng ito nang buong puso. Ito ang pundasyon ng pundasyon. Ang anotasyong ito ay nagbibigay-daan sa mga bagay ng iyong Java class na mai-mapa sa isang database. Para maging entity ang isang klase, dapat nitong matugunan ang mga sumusunod na kinakailangan:
  • Dapat itong may walang laman na constructor ( publico protected)
  • Hindi ito maaaring nested, isang interface o isangenum
  • Hindi ito maaaring finalat hindi maaaring magkaroon ng finalmga field/properties
  • Dapat ay mayroon itong kahit isang field ng @Id.
Suriin ang iyong mga klase sa entity: ang mga ito ay napakasikat na lugar para kunan ang iyong sarili sa paa. Napakadaling kalimutan ang isang bagay. Bukod dito, maaaring gawin ng isang entity ang sumusunod:
  • Maaari itong magkaroon ng mga hindi walang laman na konstruktor
  • Maaari itong magmana at mamana
  • Maaari itong magkaroon ng iba pang mga pamamaraan at magpatupad ng mga interface.
Tulad ng nakikita mo, ang Userklase ay halos kapareho sa talahanayan ng mga gumagamit. Mayroon itong id, name, atagemga patlang. Ang mga anotasyon na matatagpuan sa itaas ng mga ito ay hindi nangangailangan ng anumang partikular na paliwanag: malinaw na ang @Id ay nagpapahiwatig na ang field ay isang identifier ng mga bagay ng klase na ito. Ang @Table annotation sa itaas ng klase ay nagpapahiwatig ng pangalan ng talahanayan kung saan nakasulat ang mga bagay. Tandaan ang komento sa itaas ng field ng edad: kung ang pangalan ng field sa klase ay pareho sa pangalan ng talahanayan, maaari mong alisin ang @Column annotation at gagana ito. Tulad ng para sa bahaging ipinahiwatig sa mga braces ("diskarte = GenerationType.IDENTITY"): mayroong ilang mga diskarte para sa pagbuo ng mga ID. Maaari mong i-Google ang mga ito, ngunit para sa aming aplikasyon, hindi na kailangang mag-abala. Ang pangunahing bagay ay na para sa aming mga bagay ang halaga ng id ay awtomatikong bubuo. Alinsunod dito, walang setter para sa id, at hindi rin namin ito itinatakda sa constructor. gayunpaman,Userkakaiba ang klase. Mayroon itong listahan ng mga kotse! Ang iyong unang Hibernate application - 11Ang @OneToMany annotation ay nakabitin sa itaas ng listahan. Nangangahulugan ito na maraming mga kotse ang maaaring tumugma sa parehong bagay ng klase ng User. Ang elementong "mappedBy" ay tumutukoy sa field ng user ng Autoklase. Kaya, ang mga kotse at mga gumagamit ay magkakaugnay. Isinasaad ng orphanRemoval element kung ilalapat ang pagpapatakbo ng pag-alis sa mga entity na wala nang kaugnayan. Kung magde-delete kami ng user sa database, tatanggalin din ang lahat ng kotseng nauugnay dito. Sa turn, saAutoclass, makikita mo ang field ng user na may @ManyToOne annotation (isang User ay maaaring tumutugma sa maraming Autos) at ang @JoinColumn annotation. Ipinapahiwatig nito kung aling column sa talahanayan ng autos ang ginagamit upang i-reference ang talahanayan ng mga user (ibig sabihin, ang foreign key na napag-usapan natin kanina). Pagkatapos gawin ang modelo ng data, oras na para turuan ang aming programa na magsagawa ng mga operasyon gamit ang data sa database. Magsimula tayo sa klase ng utility na HibernateSessionFactoryUtil. Isa lang ang trabaho nito — gumawa ng factory ng session para gumana ang aming application sa database (kumustahin ang pattern ng disenyo ng Factory!). Hindi na ito marunong gumawa ng iba.

 package utils;
 
 import models.Auto;
 import models.User;
 import org.hibernate.SessionFactory;
 import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
 import org.hibernate.cfg.Configuration;
 
 public class HibernateSessionFactoryUtil {
     private static SessionFactory sessionFactory;
 
     private HibernateSessionFactoryUtil() {}
 
     public static SessionFactory getSessionFactory() {
         if (sessionFactory == null) {
             try {
                 Configuration configuration = new Configuration().configure();
                 configuration.addAnnotatedClass(User.class);
                 configuration.addAnnotatedClass(Auto.class);
                 StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
                 sessionFactory = configuration.buildSessionFactory(builder.build());
 
             } catch (Exception e) {
                 System.out.println("Исключение!" + e);
             }
         }
         return sessionFactory;
     }
 }
 
Sa klase na ito, lumikha kami ng bagong Configuration object, at ipapasa dito ang mga klase na dapat nitong ituring bilang mga entity: Userat Auto. Bigyang-pansin ang configuration.getProperties()pamamaraan. Ano ang iba pang mga katangian doon? Saan sila nanggaling? Ang mga katangian ay ang mga setting ng hibernate na nakasaad sa espesyal na hibernate.cfg.xml file. Ang iyong unang Hibernate application - 12Ang Hibernate.cfg.xml ay binasa dito: new Configuration().configure(); Tulad ng nakikita mo, walang partikular na espesyal tungkol dito: naglalaman ito ng mga parameter para sa pagkonekta sa database, pati na rin ang show_sql parameter. Ito ay kinakailangan upang ang lahat ng sql query na isinagawa ng Hibernate ay maipakita sa console. Sa ganitong paraan makikita mo nang eksakto kung ano ang ginagawa ng Hibernate sa anumang naibigay na sandali, inaalis ang anumang kahulugan ng "magic". Susunod na kailangan namin angUserDAOklase. Ang pinakamahusay na kasanayan ay magprograma sa pamamagitan ng mga interface — lumikha ng isang hiwalay UserDAOna interface at UserDAOImplpagpapatupad, ngunit laktawan ko ito upang mabawasan ang dami ng code. Huwag gawin ito sa mga totoong proyekto! Ang pattern ng disenyo ng DAO (data access object) ay isa sa pinakakaraniwan. Ang ideya ay simple — lumikha ng isang layer ng application na responsable lamang para sa pag-access ng data, wala nang iba pa. Kunin ang data mula sa database, i-update ang data, tanggalin ang data — iyon lang. Mag-aral pa tungkol sa DAO. Patuloy kang gagamit ng mga bagay sa pag-access ng data sa iyong trabaho. Ano ang UserDaomagagawa ng aming klase? Well, tulad ng lahat ng DAO, maaari lamang itong gumana sa data. Maghanap ng user sa pamamagitan ng id, i-update ang data nito, tanggalin ito, kumuha ng listahan ng lahat ng user mula sa database, o mag-save ng bagong user sa database — iyon ang kabuuan ng functionality nito.

 package dao;
 
 import models.Auto;
 import models.User;
 import org.hibernate.Session;
 import org.hibernate.Transaction;
 import utils.HibernateSessionFactoryUtil;
 import java.util.List;
 
 public class UserDao {
 
     public User findById(int id) {
         return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(User.class, id);
     }
 
     public void save(User user) {
         Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
         Transaction tx1 = session.beginTransaction();
         session.save(user);
         tx1.commit();
         session.close();
     }
 
     public void update(User user) {
         Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
         Transaction tx1 = session.beginTransaction();
         session.update(user);
         tx1.commit();
         session.close();
     }
 
     public void delete(User user) {
         Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
         Transaction tx1 = session.beginTransaction();
         session.delete(user);
         tx1.commit();
         session.close();
     }
 
     public Auto findAutoById(int id) {
         return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Auto.class, id);
     }
 
     public List<User> findAll() {
         List<User> users = (List<User>) HibernateSessionFactoryUtil.getSessionFactory().openSession().createQuery("From User").list();
         return users;
     }
 }
 
UserDaoAng mga pamamaraan ni ay katulad sa isa't isa. Sa karamihan sa mga ito, nakakakuha kami ng object ng Session (session ng koneksyon sa database) gamit ang aming Session Factory, lumikha ng isang transaksyon sa loob ng session na ito, isagawa ang mga kinakailangang manipulasyon ng data, i-save ang resulta ng transaksyon sa database, at pagkatapos ay isara ang session. Ang mga pamamaraan mismo, tulad ng nakikita mo, ay medyo simple. Ang DAO ay ang "puso" ng aming aplikasyon. Gayunpaman, hindi kami direktang lilikha ng DAO at tatawagin ang mga pamamaraan nito sa aming main()pamamaraan. Ang lahat ng lohika ay ililipat sa UserServiceklase.

 package services;
 
 import dao.UserDao;
 import models.Auto;
 import models.User;
 
 import java.util.List;
 
 public class UserService {
 
     private UserDao usersDao = new UserDao();
 
     public UserService() {
     }
 
     public User findUser(int id) {
         return usersDao.findById(id);
     }
 
     public void saveUser(User user) {
         usersDao.save(user);
     }
 
     public void deleteUser(User user) {
         usersDao.delete(user);
     }
 
     public void updateUser(User user) {
         usersDao.update(user);
     }
 
     public List<User> findAllUsers() {
         return usersDao.findAll();
     }
 
     public Auto findAutoById(int id) {
         return usersDao.findAutoById(id);
     }
 
 
 }
 
 
Ang Serbisyo ay isang layer ng data ng application na responsable para sa pagpapatupad ng lohika ng negosyo. Kung ang iyong programa ay kailangang magsagawa ng ilang uri ng lohika ng negosyo, ginagawa ito sa pamamagitan ng mga serbisyo. Ang isang serbisyo ay naglalaman ng UserDaoat tinatawag na mga pamamaraan ng DAO sa mga pamamaraan nito. Maaaring tila kami ay nagdodoble ng mga pag-andar dito (bakit hindi na lang tawagan ang mga pamamaraan mula sa isang DAO object?), ngunit sa maraming mga bagay at kumplikadong lohika, ang layering ng application ay nagbibigay ng malaking pakinabang (ang paggawa nito ay mabuting kasanayan - tandaan ito sa hinaharap at basahin ang tungkol sa "mga layer ng application"). Ang aming serbisyo ay may simpleng lohika, ngunit ang mga pamamaraan ng serbisyo sa mga real-world na proyekto ay naglalaman ng higit sa isang linya ng code :) Ngayon ay mayroon na kaming lahat ng kailangan mo upang patakbuhin ang application! Sa main()pamamaraan, gumawa tayo ng isang user at ang kotse nito, iugnay ang isa sa isa, at i-save ang mga ito sa database.

 import models.Auto;
 import models.User;
 import services.UserService;
 
 import java.sql.SQLException;
 
 public class Main {
     public static void main(String[] args) throws SQLException {
 
         UserService userService = new UserService();
         User user = new User ("Jenny", 26);
         userService.saveUser(user);
         Auto ferrari = new Auto("Ferrari", "red");
         ferrari.setUser(user);
         user.addAuto(ferrari);
         Auto ford = new Auto("Ford", "black");
         ford.setUser(user);
         user.addAuto(ford);
         userService.updateUser(user);
     }
 }
 
 
Tulad ng nakikita mo, ang talahanayan ng mga gumagamit ay may sariling tala, at ang talahanayan ng autos ay may sariling tala. Ang iyong unang Hibernate application - 13Ang iyong unang Hibernate application - 14Subukan nating palitan ang pangalan ng ating user. I-clear ang talahanayan ng mga user at isagawa ang code

 import models.Auto;
 import models.User;
 import services.UserService;
 
 import java.sql.SQLException;
 
 public class Main {
     public static void main(String[] args) throws SQLException {
 
         UserService userService = new UserService();
         User user = new User ("Jenny", 26);
         userService.saveUser(user);
         Auto ferrari = new Auto("Ferrari", "red");
         user.addAuto(ferrari);
         Auto ford = new Auto("Ford", "black");
         ford.setUser(user);
         user.addAuto(ford);
         userService.updateUser(user);
         user.setName ("Benny");
         userService.updateUser(user);
     }
 }
 
 
Gumagana siya! Ang iyong unang Hibernate application - 15Paano kung tanggalin mo ang gumagamit? I-clear ang talahanayan ng mga user (ko-clear ng autos ang sarili nito) at i-execute ang code

 import models.Auto;
 import models.User;
 import services.UserService;
 
 import java.sql.SQLException;
 
 public class Main {
     public static void main(String[] args) throws SQLException {
 
         UserService userService = new UserService();
         User user = new User ("Jenny", 26);
         userService.saveUser(user);
         Auto ferrari = new Auto("Ferrari", "red");
         user.addAuto(ferrari);
         Auto ford = new Auto("Ford", "black");
         ford.setUser(user);
         user.addAuto(ford);
         userService.updateUser(user);
         user.setName ("Benny");
         userService.updateUser(user);
         userService.deleteUser(user);
     }
 }
 
 
At ang aming mga talahanayan ay ganap na walang laman (bigyang-pansin ang console — lahat ng mga kahilingan na ginawa ng Hibernate ay ipapakita doon). Maaari kang makipaglaro sa application at subukan ang lahat ng mga function nito. Halimbawa, lumikha ng isang user na may mga kotse, i-save ito sa database, tingnan ang id na itinalaga sa user, at subukang gamitin ang id na ito samain()paraan upang kunin ang user mula sa database at magpakita ng listahan ng mga sasakyan nito sa console. Siyempre, maliit na bahagi lang ng functionality ng Hibernate ang nakita namin. Napakalawak ng mga kakayahan nito, at matagal na itong karaniwang tool sa industriya para sa pagpapaunlad ng Java. Kung nais mong pag-aralan ito nang detalyado, maaari kong irekomenda ang aklat na "Java Persistence API at Hibernate". Sinuri ko sa isang nakaraang artikulo. Sana ay nakatulong ang artikulong ito sa mga mambabasa. Kung mayroon kang mga katanungan, tanungin sila sa mga komento. I will be happy to answer :) Gayundin, huwag kalimutang suportahan ang may-akda sa patimpalak sa pamamagitan ng pag-post ng "Like". Or better yet — "Love it" :) Good luck sa pag-aaral mo!
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION