JavaRush /Java блогу /Random-KY /Сиздин биринчи күтүү колдонмоңуз
Джон Дориан
Деңгээл

Сиздин биринчи күтүү колдонмоңуз

Группада жарыяланган
Бул макалада сиз Java үчүн эң популярдуу ишкана алHowтарынын бири менен таанышасыз жана Hibernate аркылуу биринчи тиркемеңизди түзөсүз. Hibernate жөнүндө уккан эмес белеңиз? Балким сиз бул тууралуу уккандырсыз, бирок колдоно элексизби? Же баштоого аракет кылды, бирок ийгorкке жеткен жок? Үч учурда тең, кесипке кош келиңиз :) Сиздин биринчи Күтүү колдонмоңуз - 1Баарына салам! Бул макалада мен Hibernate алкагынын негизги өзгөчөлүктөрү жөнүндө айтып берем жана биринчи мини-тиркемени жазууга жардам берем. Бул үчүн бизге керек:
  1. Intellij Idea Ultimate Edition; Расмий веб-сайттан
    жүктөп алып , 30 күндүк сыноо versionсын иштетиңиз.
  2. PostgeSQL - эң популярдуу заманбап маалымат базасын башкаруу системаларынын бири (DBMS);
  3. Maven (IDEAга мурунтан эле орнотулган);
  4. Бир аз сабыр.
Макала биринчи кезекте бул технология менен эч качан иштебегендерге багытталган, ошондуктан codeдун көлөмү мүмкүн болушунча кыскартылды. Баштайлы!

Hibernate деген эмне?

Бул ORM моделинин эң популярдуу ишке ашырууларынын бири. Объект-реляциялык модель программалык an objectилер менен маалыматтар базасындагы жазуулардын ортосундагы мамилелерди сүрөттөйт. Албетте, Hibernate функциясынын мүмкүнчүлүктөрү абдан кенен, бирок биз эң жөнөкөй функцияларга токтолобуз. Биздин максат: CRUD тиркемесин түзүү (Түзүү, Окуу, Жаңыртуу, Жок кылуу) ал:
  1. Колдонуучуларды (Колдонуучуну) түзүңүз, ошондой эле аларды ID боюнча маалымат базасында издеңиз, алардын маалымат базасындагы маалыматтарын жаңыртыңыз, ошондой эле маалымат базасынан жок кылыңыз.
  2. Колдонуучуларга унаа an objectтерин (Авто) дайындоо. Автоунааларды түзүү, түзөтүү, маалымат базасынан табуу жана жок кылуу.
  3. Кошумчалай кетсек, тиркеме автоматтык түрдө маалымат базасынан “жетим” унааларды алып салышы керек. Ошол. Колдонуучу жок кылынганда, ага тиешелүү бардык унаалар да маалымат базасынан өчүрүлүшү керек.
Биздин долбоордун түзүмү төмөнкүчө болот: Сиздин биринчи күтүү колдонмоңуз - 2Көрүнүп тургандай, эч нерсе татаал эмес. 6 класс + конфигурациялары бар 1 файл. Биринчиден, Intellij Ideaда жаңы maven долбоорун түзөлү. Файл -> Жаңы долбоор. Сунушталган долбоордун түрлөрүнөн Mavenди тандап, улантыңыз. Сиздин биринчи күтүү колдонмоңуз - 3Apache Maven бул POM тorндеги файлдарда алардын структурасынын сыпаттамасынын негизинде долбоорлорду чогултууну автоматташтыруу үчүн негиз. Долбооруңуздун бүт структурасы pom.xml файлында сүрөттөлөт, аны IDEA өзү долбооруңуздун тамырында түзөт. Долбоордун жөндөөлөрүндө сиз Maven параметрлерин көрсөтүшүңүз керек - groupId жана artifactId. Адатта, долбоорлордо groupId бул уюмдун же бөлүмдүн аталышы, ал эми уюмдун же долбоордун сайтынын домендик аталышы ошол жерде жазылат. Өз кезегинде, artefactId долбоордун аты. groupdId үчүн сиз белгилей аласыз com.вашНикнейм.javarush, бул колдонмонун иштешине эч кандай таасир тийгизбейт. artifactId үчүн, каалаган долбоордун атын тандаңыз. Сиз ошондой эле Версияны өзгөртүүсүз калтырсаңыз болот. Сиздин биринчи күтүү колдонмоңуз - 4Акыркы экранда, жөн гана мурун киргизилген маалыматтарды ырастоо. Сиздин биринчи күтүү колдонмоңуз - 5Ошентип, биз долбоорду түздүк, codeду жазып, аны иштетүү гана калды :) Биринчиден, эгерде биз маалымат базасы менен иштеген тиркемени түзгүбүз келсе, анда биз сөзсүз түрдө маалымат базасысыз иштей албайбыз! PostgreSQLди бул жерден жүктөп алыңыз (мен 9 versionсын колдоном). PostgreSQLде демейки колдонуучу "postgres" бар, орнотуу учурунда ага сырсөз түзүшүңүз керек болот. Сырсөзүңүздү унутпаңыз, ал бизге кийинчерээк керек болот! (Жалпысынан, тиркемелерде демейки маалымат базасын колдонуу жаман практика, бирок геморройдун санын азайтуу үчүн биз өзүбүздүн маалымат базасын түзүү менен алектенебиз). Эгер сизге буйрук сабы жана SQL сурамдары жакпаса, анда жакшы жаңылык бар. Intellij IDEA маалымат базасы менен иштөө үчүн абдан ылайыктуу колдонуучу интерфейсин камсыз кылат. Бул төмөнкүдөй көрүнөт: Сиздин биринчи күтүү колдонмоңуз - 6(IDEAнын оң жагында жайгашкан, Маалыматтар базасы өтмөгү) Байланыш түзүү үчүн, "+" баскычын басыңыз, провайдерибизди (PostgeSQL) тандаңыз. Колдонуучу, маалымат базасынын аты (экөө тең postgres) менен талааларды толтуруңуз жана PostgreSQLди орнотуп жатканда койгон сырсөзүңүздү киргизиңиз. Зарыл болсо, Postgres драйверин жүктөп алыңыз, муну ушул эле бетте жасаса болот. Маалыматтар базасына туташуу орнотулганын текшерүү үчүн "Тест туташуусун" басыңыз. Эгер сиз "Ийгorктүү" деген жазууну көрсөңүз, биз улантабыз. Эми бизге керектүү tableларды түзөлү. Алардын экөө болот - колдонуучулар жана авто. Колдонуучулардын tableсы үчүн параметрлер: Күтүү режиминдеги биринчи колдонмоңуз - 7id негизги ачкыч экенин эске алыңыз. Эгер сиз SQLде негизги ачкыч деген эмне экенин билбесеңиз, анда Google'га кайрылыңыз, бул маанилүү. Автоматтык столдун жөндөөлөрү: Күтүү режиминдеги биринчи колдонмоңуз - 8Автоунаалар үчүн тышкы ачкычты конфигурациялашыңыз керек - тышкы ачкыч. Ал биздин үстөлдөрдү байланыштырат. Мен сизге ал жөнүндө көбүрөөк окууну сунуштайм; Жөнөкөй сөз менен айтканда, бул тышкы tableга, биздин учурда колдонуучуларга тиешелүү. Эгерде унаа id=1 болгон колдонуучуга таандык болсо, анда autos tableсынын user_id талаасында 1 болот. Колдонмобуздагы колдонуучуларды унаалары менен ушинтип байланыштырабыз. Биздин autos tableда user_id талаасы чет элдик ачкыч катары кызмат кылат. Ал колдонуучулар tableсынын id талаасына кайрылат. Сиздин биринчи Күтүү колдонмоңуз - 9Ошентип, биз эки tableдан турган маалымат базасын түздүк. Аны Java codeунан кантип башкарууну түшүнүү керек. Биз pom.xml файлынан баштайбыз, ага керектүү китепканаларды киргизишибиз керек (мавен тorнде алар көз карандылык деп аталат). Бардык китепканалар борбордук Maven репозиторийинде сакталат. Алардын сиз pom.xml ичинде көрсөткөндөрүн долбоордо колдоно аласыз. Сиздин pom.xml төмөнкүдөй болушу керек: Сиздин биринчи Күтүү колдонмоңуз - 10Сиз көрүп тургандай татаал эч нерсе жок. Биз болгону 2 көз карандылыкты коштук - PostgreSQL жана Hibernate колдонуу үчүн. Эми Java codeуна өтөбүз. Долбоор үчүн бардык керектүү пакеттерди жана класстарды түзүңүз. Баштоо үчүн бизге маалымат моделдери керек болот - класстар Userжана Auto.
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 not specify Column name if it matches the name of the column 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 not specify Column name if it matches the name of the column 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;
    }
}
Көрүнүп тургандай, класстар дагы эле түшүнүксүз annotationлар менен жабдылган. Келгиле, алар менен иш алып баралы. Биз үчүн негизги annotation бул @Entity. Бул тууралуу Wikipediaдан окуп, баарын эстеп жүрүңүз, бул негиздердин негизи. Бул annotation классыңыздын Java an objectилерин маалымат базасы менен байланыштырууга мүмкүндүк берет. Класс субъект болушу үчүн, ал төмөнкү талаптарга жооп бериши керек:
  • Бош конструктор болушу керек ( publicже protected);
  • уя, интерфейс же мүмкүн эмес enum;
  • -талаалар/касиеттер болушу мүмкүн эмес finalжана камтышы мүмкүн эмес ;final
  • Кеминде бир @Id талаасын камтышы керек.
Объект класстарыңызды текшериңиз, булар өзүңүздү бутуңузга атуу үчүн абдан популярдуу жер. Бир нерсени унутуу абдан оңой. Бул учурда, уюм:
  • Бош эмес конструкторлорду камтыйт;
  • мураскор болуу жана мураскор болуу;
  • Башка ыкмаларды камтып, интерфейстерди ишке ашырыңыз.
Көрүнүп тургандай, класс Userколдонуучулардын tableсына абдан окшош. талаалар бар id, name, age. Алардын үстүндө жайгашкан annotationлар көп түшүндүрүүнү талап кылbyte: @Id бул талаа бул класстын an objectтеринин идентификатору экендигинин көрсөткүчү экени буга чейин эле көрүнүп турат. Класстын үстүндөгү @Table annotationсы an objectтер жазылган tableнын атын аныктайт. Курак талаасынын үстүндөгү комментарийге көңүл буруңуз: класстагы талаа аты менен table бирдей болсо, @Column annotationсын кошушуңуз керек эмес, ал ушундай иштейт. кашаада көрсөтүлгөн "стратегия = GenerationType.IDENTITY" карата: бир нече ID түзүү стратегиялары бар. Сиз аны гуглдан издесеңиз болот, бирок биздин тиркеменин алкагында убара болбошуңуз керек. Эң негизгиси, биздин an objectтердин идентификаторлору автоматтык түрдө түзүлөт, андыктан id үчүн орнотуучу жок жана биз аны конструктордо да көрсөтпөйбүз. Бирок, класс дагы эле кээ бир жагынан Userөзгөчөлөнүп турат . Ал унаалардын тизмеси бар! @OneToMany annotationсы тизменин үстүндө пайда болот. Бул колдонуучу классынын бир an objectисине бир нече машиналар туура келиши мүмкүн дегенди билдирет. "mappedBY" жөндөөсү класстын колдонуучу талаасын көрсөтөт Auto. Ошентип, машиналар жана колдонуучулар бири-бири менен байланышкан. orphanRemoval жөндөө англис тorнен абдан жакшы которулат - "remove orphons". Эгер биз маалымат базасынан колдонуучуну жок кылсак, аны менен байланышкан бардык унаалар да өчүрүлөт. Өз кезегинде, класста Autoсиз @ManyToOne annotationсы бар колдонуучу талаасын көрөсүз (көптөгөн Автоматтар бир Колдонуучуга туура келиши мүмкүн) жана @JoinColumn annotationсы. Ал колдонуучулардын tableсы менен байланыштын autos tableсынын кайсы тилкеси аркылуу ишке ашканын көрсөтөт (башкача айтканда, ошол эле тышкы ачкыч). Берorштер моделин түзгөндөн кийин, бул маалымат базасында бул маалыматтар боюнча операцияларды аткаруу үчүн биздин программаны үйрөтүү үчүн убакыт келди. HibernateSessionFactoryUtil утorта классынан баштайлы. Анын бир гана милдети бар - биздин тиркеме үчүн маалымат базасы менен иштөө үчүн сеанс фабрикасын түзүү (салам, "Завод!" үлгүсү). Анын колунан башка эч нерсе келбейт.
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("Exception!" + e);
            }
        }
        return sessionFactory;
    }
}
Бул класста биз жаңы конфигурация an objectисин, Конфигурацияны түзөбүз жана ага an object катары кабыл алышы керек болгон класстарды өткөрүп беребиз - Userжана Auto. Усулга көңүл буруңуз configuration.getProperties(). Дагы кандай касиеттери? Кайда? Сипаттар - hibernate.cfg.xml атайын файлында көрсөтүлгөн, күтүү режиминин иштешинин параметрлери. Сиздин биринчи Күтүү колдонмоңуз - 11Hibernate.cfg.xml бул жерден окулат: new Configuration().configure(); Көрүнүп тургандай, анда өзгөчө эч нерсе жок - маалымат базасына туташуу үчүн параметрлер жана show_sql атайын параметри. Бул биздин маалымат базасына каршы күтүү режиминде турган бардык SQL сурамдары консолго чыгышы үчүн керек. Ошентип, сиз Гибернаттын ар бир көз ирмемде эмне кылып жатканын так көрүп, "сыйкырдуу" эффекттен арыласыз. Андан кийин бизге класс керек UserDAO. (Жакшы жол менен интерфейстер аркылуу программалоо керек - интерфейс түзүп UserDAO, аны өзүнчө ишке ашырышыңыз керек UserDAOImpl, бирок codeдун көлөмүн азайтуу үчүн мен муну өткөрүп жиберем. Муну реалдуу долбоорлордо жасабаңыз!). DAO (маалыматтарга кирүү an objectи) эң кеңири таралган дизайн үлгүлөрүнүн бири, "Маалыматтарга жетүү". Анын мааниси жөнөкөй - тиркемеде маалыматтарга жетүү үчүн гана жооптуу катмарды түзүү жана башка эч нерсе жок. Маалыматтар базасынан маалыматтарды алыңыз, маалыматтарды жаңыртыңыз, маалыматтарды жок кылыңыз - жана ушуну менен. DAOs жөнүндө көбүрөөк окуңуз; сиз аларды жумушуңузда дайыма колдоносуз. Биздин класс эмне кыла алат UserDao? Чынында, бардык DAO сыяктуу эле, ал маалыматтар менен гана иштей алат. Идентификатор боюнча колдонуучуну табыңыз, анын маалыматтарын жаңыртыңыз, жок кылыңыз, маалымат базасынан бардык колдонуучулардын тизмесин чыгарыңыз же жаңы колдонуучуну маалымат базасында сактаңыз - анын бардык функциялары.
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;
    }
}
Методдор UserDaoбири-бирине окшош. Алардын көпчүлүгүндө биз Session Factory аркылуу Сессия an objectисин (биздин маалыматтар базасына туташкан сессия) алабыз, бул сессиянын ичинде бирдиктүү транзакция түзөбүз, керектүү маалыматтарды трансформациялайбыз, транзакциянын жыйынтыгын маалымат базасына сактап жана сессияны жабабыз. Көрүнүп тургандай, ыкмалары абдан жөнөкөй. DAO биздин колдонмонун "жүрөгү" болуп саналат. Бирок, биз түздөн-түз DAO түзбөйбүз жана анын ыкмаларын биздин main(). Бардык логикага жылдырылат UserService.
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);
    }


}
Кызмат - бул бизнес логикасын аткаруу үчүн жооптуу болгон тиркемедеги маалымат катмары. Эгерде сиздин программаңыз кандайдыр бир бизнес логикасын аткарышы керек болсо, ал муну кызматтар аркылуу кылат. Кызмат өзүнүн ичинде камтыйт UserDaoжана анын ыкмаларында DAO ыкмаларын чакырат. Бул сизге функциялардын кайталанышы сыяктуу көрүнүшү мүмкүн (эмне үчүн жөн гана дао an objectинен методдорду чакыруу эмес), бирок көп сандагы an objectилер жана татаал логика менен тиркемени катмарларга бөлүү чоң артыкчылыктарга ээ (бул жакшы практика, бул маалыматты эстеп калуу үчүн келечек жана "колдонмо катмарлары" жөнүндө окуу "). Биздин кызматта логика жөнөкөй, бирок реалдуу долбоорлордо тейлөө ыкмалары бир нече сап codeду камтыйт :) Эми бизде тиркеменин иштеши үчүн бардык нерсе бар! main()Ал үчүн методдо колдонуучуну жана машиналарды түзүп , аларды бири-бири менен байланыштырып, маалымат базасында сактайлы.
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("Masha",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);
    }
}
Көрүнүп тургандай, колдонуучулар tableсынын өзүнүн жазуусу бар, ал эми autos tableсынын өзүнүн жазуусу бар. Сиздин биринчи Күтүү колдонмоңуз - 13Сиздин биринчи Күтүү колдонмоңуз - 14Келгиле, колдонуучунун атын өзгөртүүгө аракет кылалы. Келгиле, колдонуучулардын tableсын тазалап, 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("Masha",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("Sasha");
        userService.updateUser(user);
    }
}
Works! Сиздин биринчи Күтүү колдонмоңуз - 15Эгер колдонуучуну жок кылсаңызчы? Келгиле, колдонуучулардын tableсын тазалайлы (автоматтар өзүн тазалайт) жана 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("Masha",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("Sasha");
        userService.updateUser(user);
        userService.deleteUser(user);
    }
}
Жана биздин tableлар толугу менен бош (консолго көңүл буруңуз, Hibernate аткарган бардык сурамдар ошол жерде көрсөтүлөт). Сиз колдонмо менен ойноп, анын бардык мүмкүнчүлүктөрүн сынап көрүңүз. Мисалы, машиналары бар колдонуучуну түзүп, аны маалымат базасында сактап, ага кандай идентификатор ыйгарылганын көрүп, main()ушул идентификатор боюнча колдонуучуну маалымат базасынан “тартып алуу” ыкмасын колдонуп көрүңүз жана анын машиналарынын тизмесин консолдо көрсөтүңүз. . Албетте, биз Hibernate функциясынын кичинекей бөлүгүн гана көрдүк. Анын мүмкүнчүлүктөрү абдан кенен жана ал көптөн бери Java өнүктүрүү үчүн тармактык стандарттардын бири болуп келген. Эгер сиз аны майда-чүйдөсүнө чейин изилдегиңиз келсе, мен мурунку макалаларымдын биринде карап чыккан "Java Persistence API жана Hibernate" китебин сунуш кыла алам . Бул макала окурмандар үчүн пайдалуу болду деп үмүттөнөм. Суроолоруңуз болсо, комментарийлерде бериңиз, мен кубаныч менен жооп берем :) Ошондой эле, сынакта авторго "Лайк" басып колдоо көрсөтүүнү унутпаңыз. Же андан да жакшысы - “Мага абдан жагат” :) Окууңарга ийгorк!
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION