பிரச்சனையின் விளக்கம்

நாம் மேலே கூறியது போல், LazyCollectionOption.EXTRA சிறுகுறிப்பில் சிக்கல் உள்ளது - இது ஒவ்வொரு பொருளுக்கும் தரவுத்தளத்திற்கு ஒரு தனி கோரிக்கையை செய்கிறது. நாம் எப்படியாவது Hibernate க்கு விளக்க வேண்டும், அது உடனடியாக நம் பெற்றோர் பொருட்களுக்கான அனைத்து குழந்தை பொருட்களையும் ஏற்ற வேண்டும்.

Hibernate இன் டெவலப்பர்கள் இந்தப் பிரச்சனைக்கு ஒரு தீர்வைக் கொண்டு வந்துள்ளனர், HQL இல் ஜாயின் ஃபெட்ச் ஆபரேட்டர் .

HQL வினவல் உதாரணம்:

select distinct task from Task t left join fetch t.employee order by t.deadline

இந்த வினவலில், எல்லாம் ஒரே நேரத்தில் எளிமையானது மற்றும் சிக்கலானது. அதை துண்டு துண்டாக உருவாக்க முயற்சிப்போம்.

விருப்பம் 1

அனைத்து பொருட்களையும் பதிவிறக்கம் செய்ய விரும்புகிறோம்பணி, காலக்கெடுவால் வரிசைப்படுத்தப்பட்டது. அந்த கோரிக்கை எப்படி இருக்கும் என்பது இங்கே:

select task from Task t order by t.deadline

எல்லாம் தெளிவாக இருக்கும்போது. ஆனால் களம்பணியாளர்பணி வகுப்பில் , கூடுதல் சிறுகுறிப்புடன் குறிப்பிடப்பட்ட பணியாளர்களின் தொகுப்பு இருக்கும் . மேலும் இந்தத் தொகுப்பின் பொருள்கள் ஏற்றப்படாது.

விருப்பம் 2

ஒரு பொருளுக்கு குழந்தை பொருட்களை ஏற்ற ஹைபர்னேட்டை கட்டாயப்படுத்தவும்பணி.

select task from Task t join fetch t.employee order by t.deadline

உதவியுடன், எங்கள் வினவலில் பணி மற்றும் பணியாளர் நிறுவனங்களை வெளிப்படையாக பிணைக்கிறோம். இந்தப் புலங்களில் @ManyToMany சிறுகுறிப்புகளைப் பயன்படுத்துவதால், Hibernateக்கு இது ஏற்கனவே தெரியும் .

ஆனால், ஜாயின் ஃபெட்ச் பெற , பெறுதல் அறிக்கையுடன் அதை முடிக்க , எங்களுக்கு ஒரு ஜாயின் ஸ்டேட்மெண்ட் தேவை . எங்கள் கோரிக்கையை நிறைவேற்றும்போது, ​​Task.employee சேகரிப்பில் உள்ள பொருள்கள் தரவுத்தளத்திலிருந்து ஏற்றப்பட வேண்டும் என்று Hibernate க்கு இப்படித்தான் சொல்கிறோம்.

விருப்பம் 3

முந்தைய தீர்வில் சில பிழைகள் உள்ளன. முதலில், join ஐப் பயன்படுத்திய பிறகு, SQL நமக்கு பொருட்களைத் திருப்பித் தராதுபணி, பணியாளர் அட்டவணையில் அவற்றுடன் தொடர்புடைய பொருள்கள் எதுவும் இல்லை. உள் இணைப்பு வேலை செய்வது இப்படித்தான் .

எனவே நாம் ஒரு இடது ஆபரேட்டரைக் கொண்டு நமது இணைப்பை அதிகரிக்க வேண்டும் மற்றும் அதை இடது இணைப்பாக மாற்ற வேண்டும் . உதாரணமாக:

select task from Task t left join fetch t.employee order by t.deadline

விருப்பம் 4

ஆனால் அதெல்லாம் இல்லை. உங்கள் குறியீட்டில் உள்ளமைவுகளுக்கிடையேயான தொடர்பு பல முதல் மே வரை இருந்தால், வினவல் முடிவுகளில் நகல்கள் இருக்கும். அதே பொருள்பணிவெவ்வேறு பணியாளர்களில் (பணியாளர் பொருள்கள்) காணலாம்.

எனவே, டூப்ளிகேட் டாஸ்க் ஆப்ஜெக்ட்டை அகற்ற, தேர்ந்தெடுக்கப்பட்ட வார்த்தைக்குப் பிறகு தனித்துவமான முக்கிய சொல்லைச் சேர்க்க வேண்டும்.

select distinct task from Task t left join fetch t.employee order by t.deadline

இப்படித்தான் 4 படிகளில் நாங்கள் தொடங்கிய கோரிக்கைக்கு வந்தோம். சரி, ஜாவா குறியீடு மிகவும் எதிர்பார்க்கப்படுகிறது:

String hql = " select distinct task from Task t left join fetch t.employee order by t.deadline";
Query<Task> query = session.createQuery( hql, Task.class);
return query.list();

FETCH வரம்புகளில் சேரவும்

யாரும் சரியானவர்கள் இல்லை. அறிக்கை பெறவும். இது சில வரம்புகளைக் கொண்டுள்ளது. மற்றும் முதலாவது setMaxResults() மற்றும் setFirstResult() முறைகளைப் பயன்படுத்துகிறது .

JOIN FETCH அறிக்கைக்கு, எங்கள் Hibernate மிகவும் சிக்கலான வினவலை உருவாக்கும், அதில் நாங்கள் மூன்று அட்டவணைகளை ஒன்றாக இணைக்கிறோம்: பணியாளர், பணி மற்றும் பணியாளர்_பணி. உண்மையில், இது பணியாளர்கள் அல்லது பணிகளுக்கான கோரிக்கை அல்ல, ஆனால் அனைத்து அறியப்பட்ட பணியாளர்-பணி ஜோடிகளுக்கான கோரிக்கை.

SQL ஆனது அதன் வரம்பு மற்றும் OFFSET அறிக்கைகளை பணியாளர்-பணி ஜோடிகளின் வினவலுக்கு சரியாகப் பயன்படுத்தலாம். அதே நேரத்தில், HQL வினவலில் இருந்து, நாம் துல்லியமான பணிகளை (பணி) பெற விரும்புகிறோம், மேலும் எங்கள் FirstResult மற்றும் MaxResult அளவுருக்களை மறுபகிர்வு செய்தால், அவை குறிப்பாக பணிப் பொருள்களைப் பார்க்க வேண்டும்.

இப்படி குறியீடு எழுதினால்:

String hql = " select distinct task from Task t left join fetch t.employee order by t.deadline";
Query<Task> query = session.createQuery( hql, Task.class);
       	    query.setFirstResult(0);
        	   query.setMaxResults(1);
return query.list();

பின்னர் ஹைபர்னேட், FirstResult மற்றும் MaxResult ஐ SQL வினவலின் OFFSET மற்றும் LIMIT அளவுருக்களுக்கு சரியாக மாற்ற முடியாது.

அதற்கு பதிலாக, அது மூன்று விஷயங்களைச் செய்யும்:

  • SQL வினவல் பொதுவாக அட்டவணையில் இருந்து எல்லா தரவையும் தேர்ந்தெடுத்து அதை Hibernate க்கு திருப்பிவிடும்
  • ஹைபர்னேட் அதன் நினைவகத்தில் தேவையான பதிவுகளைத் தேர்ந்தெடுத்து அவற்றை உங்களிடம் திருப்பித் தரும்
  • ஹைபர்னேட் ஒரு எச்சரிக்கையை வெளியிடும்

எச்சரிக்கை இதுபோன்றதாக இருக்கும்:

WARN [org.hibernate.hql.internal.ast.QueryTranslatorImpl] HHH000104: 
firstResult/maxResults specified with collection fetch; applying in memory!