ශිශිරතාරක hbm2ddl.auto වින්‍යාසයේ ඇති විය හැකි අගයන් මොනවාද සහ ඒවා කරන්නේ කුමක්ද


1098

යාවත්කාලීනය, අපනයනය සහ ලබා දිය හැකි අගයන් ගැන වැඩි විස්තර දැන ගැනීමට මට ඇත්තෙන්ම අවශ්‍ය වන්නේ hibernate.hbm2ddl.auto
යාවත්කාලීනය භාවිතා කළ යුත්තේ කවදාද සහ කවදාද? විකල්පය කුමක්ද?

මේවා ඩීබී හරහා සිදුවිය හැකි වෙනස්කම්:

  • නව වගු
  • පැරණි වගු වල නව තීරු
  • තීරු මකා දමන ලදි
  • තීරුවක දත්ත වර්ගය වෙනස් විය
  • තීරුවක වර්ගයක් එහි ගුණාංග වෙනස් කළේය
  • වගු පහත වැටුණි
  • තීරුවක අගයන් වෙනස් විය

සෑම අවස්ථාවකම හොඳම විසඳුම කුමක්ද?

Answers:


1093

සිට ප්රජාව ප්රලේඛනය :

hibernate.hbm2ddl.auto SessionFactory නිර්මාණය කරන විට ස්කීමා ඩීඩීඑල් ස්වයංක්‍රීයව දත්ත ගබඩාවට අපනයනය කරයි. Creation-drop සමඟ, SessionFactory පැහැදිලිව වසා ඇති විට දත්ත සමුදා ක්‍රමවේදය අතහැර දමනු ඇත.

උදා: වලංගු කරන්න | යාවත්කාලීන | සාදන්න | create-drop

එබැවින් හැකි විකල්ප ලැයිස්තුව වන්නේ,

  • වලංගු කරන්න : යෝජනා ක්‍රමය වලංගු කරන්න, දත්ත සමුදායේ කිසිදු වෙනසක් නොකරයි.
  • යාවත්කාලීන කිරීම : යෝජනා ක්‍රමය යාවත්කාලීන කරන්න.
  • create : ක්‍රමාංකය නිර්මාණය කරයි, පෙර දත්ත විනාශ කරයි.
  • create-drop : සැසිය ෆැක්ටරි පැහැදිලිව වසා ඇති විට, සාමාන්‍යයෙන් යෙදුම නැවැත්වූ විට යෝජනා ක්‍රමය අතහරින්න.
  • කිසිවක් නැත : යෝජනා ක්‍රමය සමඟ කිසිවක් නොකරයි, දත්ත සමුදායේ කිසිදු වෙනසක් නොකරයි

මෙම විකල්පයන් සංවර්ධකයින්ගේ මෙවලම් වන අතර නිෂ්පාදන මට්ටමේ දත්ත සමුදායන් සඳහා පහසුකම් සැලසීමට නොවේ, ඔබට පහත සඳහන් ප්‍රශ්නය බැලීමට අවශ්‍ය විය හැකිය; ශිශිර: hbm2ddl.auto = නිෂ්පාදනයේ යාවත්කාලීන කිරීම?


14
ශිශිර ලේඛනය කියවන්න ... වලංගු අගයන් සඳහා, එය මෙසේ කියයි: "උදා" ... වෙනත් වලංගු අගයන් තිබේද?
Ta Sas

16
මම හිතන්නේ එය "උදා" යැයි කියන්නේ එය ප්‍රජා ලියකියවිලි පමණක් වන නිසා, යමෙකු හැකි සියලු අගයන් ගැන උනන්දුවක් දක්වන්නේ නම්, එය හයිබර්නේට්ගේ ජාවාඩොක් තුළ සොයාගත හැකිය. (ඔව්, ඇත්තේ එම විකල්ප හතර පමණි) docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/cfg/…
szegedi

4
validate කියනවා ක්‍රමාංකය වලංගු කරන්න, එහි තේරුම හරියටම කුමක්ද ??
හුසේන් අක්තාර් වහීඩ් ‘ගූරි’

6
ශිශිරත්වයට කිසිවක් කිරීමට අවශ්‍ය නැතිනම් ඔබට 'ආඩ්වර්ක්' හෝ 'පරවියන්' හෝ වෙනත් වචනයක් භාවිතා කළ හැකිය. ඇත්තෙන්ම මම එය නිර්දේශ කරමි.
වෝඩ්

2
Create-drop විකල්පයට කුඩා එකතු කිරීමක්. මෙම විකල්පය භාවිතා කරන්නේ නම් එය සම්පූර්ණ සැලැස්ම අතහරින්නේ නැත, එය ක්‍රියාත්මක කිරීමේදී සිතියම් ගත හැකි වගු පහත වැටේ. උදාහරණයක් ලෙස Schema S සහිත දත්ත ගබඩාවක A, B, C වගු සහ ජාවා කේතයේ A සහ ​​B සඳහා සිතියම් තිබේ නම් පමණක් ශිශිරතාරකය C වගුව අතහරින්නේ නැත.
ආදිත්‍ය

195

එය මුළුමනින්ම අක්‍රිය කිරීමට “කිසිවක් නැත” යන ලේඛනගත වටිනාකම ද ඇත.


7
හයිබර්නේට් හි ක්‍රමාංකන වලංගු කිරීම සමහර විට පරිපූර්ණ වලංගු යෝජනා ක්‍රම සඳහා අසමත් වන බැවින් මෙය සැබවින්ම ප්‍රයෝජනවත් වේ.
මයිකල් පීෆල්

මම මේ වගේ දෙයක් ඉල්ලන්නයි හිටියේ. ආරම්භක කාලය අඩු කිරීම මගේ අභිප්‍රායයි.
digao_mb

47
'හිස් නූල්' 'කිසිවක්' ට වඩා හොඳයි . 'කිසිවක්' භාවිතා කිරීමට, ඔබට අනතුරු ඇඟවීමේ පණිවිඩයක් ලැබෙනු ඇත: org.hibernate.cfg.SettingsFactory - "hibernate.hbm2ddl.auto" සඳහා හඳුනා නොගත් අගය: කිසිවක් නැත
petertc

14
මම ඒක ඇලෙව්වා. පැහැදිලිවම වලංගු නියතයක් ලෙස "කිසිවක්" එකතු කරන ලදි.
සැන්

9
මම කැමතියි "hibernate.hbm2ddl.auto = අර්තාපල්" අනෙක් අයට වඩා stackoverflow.com/a/15810379/838444
Sneg

161

වින්‍යාස කිරීමේ දේපල ලෙස හැඳින්වේ hibernate.hbm2ddl.auto

අපගේ සංවර්ධන පරිසරය තුළ අප විසින් සකස් කරන ලදී hibernate.hbm2ddl.auto=create-drop යෙදූ සෑම අවස්ථාවකම පිරිසිදු දත්ත ගබඩාවක් අතහැර දමා නිර්මාණය කිරීමට අපි කටයුතු කළෙමු. එවිට අපගේ දත්ත සමුදාය දන්නා තත්වයක පවතී.

න්‍යායට අනුව, hibernate.hbm2ddl.auto=updateඔබේ ආකෘතියේ වෙනස්කම් සහිතව ඔබේ දත්ත සමුදාය යාවත්කාලීන කිරීමට ඔබට සැකසිය හැකිය , නමුත් නිෂ්පාදන දත්ත ගබඩාවක එය විශ්වාස නොකරමි. ප්‍රලේඛනයේ පෙර සංස්කරණයක් පැවසුවේ මෙය අවම වශයෙන් පර්යේෂණාත්මක බවයි; වර්තමාන තත්වය මම නොදනිමි.

එබැවින්, අපගේ නිෂ්පාදන දත්ත සමුදාය සඳහා, සකසන්න එපා hibernate.hbm2ddl.auto- පෙරනිමිය නම් දත්ත සමුදායේ වෙනසක් සිදු නොකිරීමයි . ඒ වෙනුවට, අපි SQL ඩීඩීඑල් යාවත්කාලීන ස්ක්‍රිප්ට් එකක් අතින් සාදන්නෙමු, එය එක් අනුවාදයක සිට තවත් අනුවාදයකට වෙනස් වේ.


5
ඇත්ත වශයෙන්ම, ප්‍රලේඛනය අනුව, create-drop මඟින් දත්ත සමුදා වගු නිර්මාණය කර සැසි කම්හල පැහැදිලිවම වසා ඇති විට ඒවා පහත වැටේ. එය කරන්නේ කෙසේද නොවන සැසිය කර්මාන්ත ශාලාව නිර්මාණය කරන අවස්ථාවේදී එම වගු බස්සනවා.
ෆ්‍රාන්ස්

5
නැත, සැසිවාරය නිර්මාණය කරන විට වගු හැලීම සහ නිර්මාණය කිරීම යන දෙකම සාදන්න, ඉන්පසු සැසිවාරය වසා දැමූ විට වගු සාදන්න. Stackoverflow.com/a/6752698/1536382
ටෙස්ටෝ ටෙස්ටිනි

hibernate.hbm2ddl.auto = නිෂ්පාදනය අඩුවීම නිෂ්පාදනයේ සම්බන්ධතා කාලය ඉක්මවා යාමට හේතු වේද?
මෙට්ටයිබි

51

ඔබේ ඩීබී යාවත්කාලීන කිරීම සඳහා මම දියරමය භාවිතා කරමි . නව නිපැයුම් සංවර්ධනය කරන අතරතුර හයිබර්නේට් හි ස්කීමා යාවත්කාලීන කිරීමේ ලක්ෂණය සංවර්ධකයෙකුට පමණි. නිෂ්පාදන තත්වයක් තුළ, db උත්ශ්‍රේණි කිරීම වඩාත් ප්‍රවේශමෙන් හැසිරවිය යුතුය.


6
ඔබ නිෂ්පාදනය සඳහා hbm2ddl භාවිතා නොකළ යුත්තේ මන්දැයි stackoverflow.com/questions/221379/… බලන්න .
නේතන් වොක්ස්ලන්ඩ්

51

එය තරමක් පැරණි පෝස්ට් එකක් වුවද මම මාතෘකාව පිළිබඳ යම් පර්යේෂණ කළ පරිදි එය බෙදා ගැනීමට සිතුවෙමි.

hibernate.hbm2ddl.auto

ප්‍රලේඛනයට අනුව එයට වලංගු අගයන් හතරක් තිබිය හැකිය:

සාදන්න | යාවත්කාලීන | වලංගු කරන්න | create-drop

මෙම අගයන් පෙන්වන හැසිරීම පිළිබඳ පැහැදිලි කිරීම පහත දැක්වේ:

  • create : - schema සාදන්න, කලින් තිබූ දත්ත (එහි තිබේ නම්) නැති වී යයි
  • යාවත්කාලීන කිරීම: - දී ඇති අගයන් සමඟ යෝජනා ක්‍රමය යාවත්කාලීන කරන්න.
  • වලංගු කරන්න: - යෝජනා ක්‍රමය වලංගු කරන්න. එය ඩීබී හි කිසිදු වෙනසක් නොකරයි.
  • create-drop: - කලින් තිබූ දත්ත විනාශ කරමින් ක්‍රමලේඛය සාදන්න (එහි තිබේ නම්). SessionFactory වසා දැමූ විට එය දත්ත සමුදා ක්‍රමවේදය ද අතහැර දමයි.

සඳහන් කළ යුතු වැදගත් කරුණු පහත දැක්වේ:

  • අවස්ථාවක දී යාවත්කාලීන , ක්රමානුරූපය මෙම ඩී.බී. නොමැති, නමුත් නම්, එවිට එම ක්රමානුරූපය නිර්මාණය කර ඇත.
  • අවස්ථාවක දී වලංගුකරණය , ක්රමානුරූපය DB හි පවතී නොවේ නම්, එය නිර්මාණය කර නැත. ඒ වෙනුවට, එය දෝෂයක් ඇති කරයි: -Table not found:<table name>
  • අවස්ථාවක දී නිර්මාණය බිඳු , ක්රමානුරූපය සැසිය වසා මත පතිත නොවේ. එය පහත වැටෙන්නේ SessionFactory වසා දැමීමෙන් පමණි.
  • මම මෙම දේපල සඳහා කිසියම් වටිනාකමක් ලබා දෙන්නේ නම් (ඉහත සාකච්ඡා කළ අගයන් හතරක් වෙනුවට abc යැයි කියන්න) හෝ එය හිස්ව පවතී. එය පහත හැසිරීම පෙන්වයි:

    ඩීබී හි ස්කීමා නොමැති නම්: - එය ක්‍රමාංකය නිර්මාණය කරයි

    ඩීබී හි ස්කීමා තිබේ නම්: - යෝජනා ක්‍රමය යාවත්කාලීන කරන්න.


“යාවත්කාලීනය” භාවිතා කරන විට, එය නොපවතින නම්, ක්‍රමාංකය නිර්මාණය වනු ඇති බව සැබවින්ම ඉතා වැදගත් කරුණකි.
යුරේනෝස්

"හැසිරීම පැහැදිලි කිරීම" සහ "වැදගත් කරුණු" ප්‍රකාශ සංසන්දනය කිරීමේදී create-drop පරස්පර වේ.
VNT

2
යාවත්කාලීන කිරීම සහ හිස් කිරීම අතර වෙනස කුමක්ද?
yashjain12yj

49

පළමුව, hbm2ddlවින්‍යාස දේපල සඳහා විය හැකි අගයන් පහත දැක්වේ:

  • none- කිසිදු ක්‍රියාවක් සිදු නොකෙරේ. යෝජනා ක්‍රමය ජනනය නොවේ.
  • create-only - දත්ත සමුදාය යෝජනා ක්‍රමය ජනනය වේ.
  • drop - දත්ත සමුදාය යෝජනා ක්‍රමය අතහැර දමා පසුව නිර්මාණය වේ.
  • create - දත්ත සමුදාය යෝජනා ක්‍රමය අතහැර දමා පසුව නිර්මාණය වේ.
  • create-drop- දත්ත සමුදාය යෝජනා ක්‍රමය අතහැර දමා පසුව නිර්මාණය වේ. වසා දැමීමෙන් පසු SessionFactory, දත්ත සමුදා සැලැස්ම අත්හරිනු ඇත.
  • validate - ආයතන සිතියම් භාවිතයෙන් දත්ත සමුදා ක්‍රමවේදය වලංගු වේ.
  • update - පවතින දත්ත සමුදා ක්‍රමෝපාය වස්තු සිතියම්කරණය සමඟ සංසන්දනය කිරීමෙන් දත්ත සමුදා ක්‍රමය යාවත්කාලීන වේ.

මම වඩාත් සුලභ ශිශිර ඩීඩීඑල් පරම්පරාවේ උපාය මාර්ග සඳහා බ්ලොග් සටහනක් කැප කළෙමි :

  1. එම hibernate.hbm2ddl.auto="update" ඔබ කටයුතු එකතු කිරීම හෝ සමහර අභිරුචි පිටපත් ක්රියාත්මක මත සැලසුම් නම් පහසු නමුත් අඩු නම්යශීලී වේ.
  2. මෙම බොහෝ නම්ය ප්රවේශයක් භාවිතා කිරීමයි Flyway .

කෙසේ වෙතත්, ඔබ ෆ්ලයිවේ භාවිතා කළත්, ඔබට තවමත් ආරම්භක සංක්‍රමණ ස්ක්‍රිප්ට් උත්පාදනය කළ හැකිය hbm2ddl. දී මෙම ලිපිය , ඔබ jOOQ වගුව මාදිලිය සමග JPA සලක් ආදර්ශ ඒකාබද්ධ කළ හැකි ආකාරය අපට දැකගත හැකිය.


27

hibernate.hbm2ddl.auto සැසි ෆැක්ටරි නිර්මාණය කරන විට ස්වයංක්‍රීයව වලංගු කර ඩීඩීඑල් ක්‍රමයට අපනයනය කරයි.

පෙරනිමියෙන්, එය DB මත ස්වයංක්‍රීයව කිසිදු නිර්මාණයක් හෝ වෙනස් කිරීමක් සිදු නොකරයි. පරිශීලකයා පහත දැක්වෙන අගයන්ගෙන් එකක් සකසන්නේ නම් එය කරන්නේ ස්වයංක්‍රීයව ඩීඩීඑල් ක්‍රමලේඛ වෙනස් කිරීමයි.

  • සාදන්න - යෝජනා ක්‍රමයක් නිර්මාණය කිරීම

    <entry key="hibernate.hbm2ddl.auto" value="create">
  • යාවත්කාලීන කිරීම - පවතින යෝජනා ක්‍රම යාවත්කාලීන කිරීම

    <entry key="hibernate.hbm2ddl.auto" value="update">
  • වලංගු කරන්න - පවතින යෝජනා ක්‍රමය වලංගු කරන්න

    <entry key="hibernate.hbm2ddl.auto" value="validate">
  • create-drop - සැසියක් ආරම්භ වී අවසන් වන විට ස්වයංක්‍රීයව යෝජනා ක්‍රමය නිර්මාණය කර අතහරින්න

    <entry key="hibernate.hbm2ddl.auto" value="create-drop">

2
<entry key = "hibernate.hbm2ddl.auto" value = "none"> ගැන කුමක් කිව හැකිද?
VNT

17

ඔබේ යෙදුමේ නූල් භාවිතා කිරීමට ඔබට අවශ්‍ය නැතිනම් සහ පූර්ව නිශ්චිත නියතයන් සොයන්නේ org.hibernate.cfg.AvailableSettingsනම්, ශිශිරතාරක JAR හි ඇතුළත් කර ඇති පංතිය දෙස බලන්න , එහිදී ඔබට හැකි සෑම සැකසුම් සඳහාම නියතයක් සොයාගත හැකිය. උදාහරණයක් ලෙස ඔබේ නඩුවේ:

/**
 * Auto export/update schema using hbm2ddl tool. Valid values are <tt>update</tt>,
 * <tt>create</tt>, <tt>create-drop</tt> and <tt>validate</tt>.
 */
String HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";

5
පේළි 700+ දිගු මූලාශ්‍ර ගොනුවකට සෘජු පිළිතුරට ඉහළින් වොල් 500 ක් පමණ යොමු වන්නේ ඇයි?
පවෙල් නයිඩෝබා

... එම ප්‍රශ්නයට කිසිදු තේරුමක් නැත. දේවල් තිබෙන්නේ ඇයි? ඇයි මම මෙහෙට ආවේ?
specializt

8
  • validate: යෝජනා ක්‍රමය වලංගු කරයි, දත්ත සමුදායේ කිසිදු වෙනසක් සිදු නොවේ.
  • update: වත්මන් ක්‍රියාත්මක විමසුම සමඟ යෝජනා ක්‍රමය යාවත්කාලීන කරයි.
  • create: සෑම විටම නව යෝජනා ක්‍රම නිර්මාණය කරන අතර පෙර දත්ත විනාශ කරයි.
  • create-drop: යෙදුම නැවැත්වූ විට හෝ සැසිවාරය පැහැදිලිව වසා ඇති විට යෝජනා ක්‍රමය පහත වැටේ.

'නිල' ප්‍රලේඛන යොමුව කුමක්ද? - පුදුමයි ...
ඩර්ක් ෂූමාකර්

7

මම හිතන්නේ ඔබ ඒ ගැන අවධානය යොමු කළ යුතුයි

SchemaExport Class 

මෙම පංතිය ඔබේ වින්‍යාසය ගතික කරයි, එබැවින් ඔබට වඩාත් සුදුසු ඕනෑම ඇඳුම් කට්ටලයක් තෝරා ගැනීමට එය ඉඩ දෙයි ...

ලොව පුරාවටම [SchemaExport]


4

validate: එය ක්‍රමාංකය වලංගු කරන අතර DB හි කිසිදු වෙනසක් නොකරයි.
ඔබ සිතියම්කරණ ගොනුවේ නව තීරුවක් එකතු කර ඇති බව උපකල්පනය කර ඇතුල් කිරීමේ මෙහෙයුම සිදු කළහොත්, එය "XYZ තීරුව අස්ථානගත වී ඇත" යන ව්‍යතිරේකය විසි කරයි, මන්ද දැනට පවතින යෝජනා ක්‍රමය ඔබ ඇතුළු කිරීමට යන වස්තුවට වඩා වෙනස් ය. ඔබ එම නව තීරුව අතින් එකතු කිරීමෙන් වගුව වෙනස් කරන්නේ නම්, ඇතුළු කිරීමේ මෙහෙයුම සිදු කරන්න, එවිට එය අනිවාර්යයෙන්ම නව තීරුව සමඟ සියලු තීරු වගුවට ඇතුළත් කරනු ඇත. එයින් අදහස් කරන්නේ එය දැනට පවතින යෝජනා ක්‍රම / වගුවෙහි කිසිදු වෙනසක් / වෙනස් කිරීමක් නොකරන බවයි.

update: ඔබ ක්‍රියා කරන විට එය දත්ත සමුදායේ පවතින වගුව වෙනස් කරයි. Hbm2ddl හි මෙම විකල්පය සමඟ ඔබට තීරු එක් කිරීමට හෝ ඉවත් කිරීමට හැකිය. නමුත් ඔබ 'NOT NULL' යනුවෙන් නව තීරුවක් එක් කිරීමට යන්නේ නම්, එම තීරුව DB වෙත එක් කිරීම නොසලකා හරිනු ඇත. පවතින වගුවට 'NOT NULL' තීරුවක් එක් කිරීමට අවශ්‍ය නම් වගුව හිස් විය යුතුය.


3

5.0 සිට , ඔබට දැන් එම අගයන් කැපවීමකින් සොයාගත හැකිය Enum: org.hibernate.boot.SchemaAutoTooling(අගය සමඟ වැඩි දියුණු කරන ලදිNONE 5.2 සිට ).

හෝ ඊටත් වඩා හොඳයි, 5.1 සිට , ඔබට JPA 2 සහ "උරුමය" හයිබර්නේට් ඩීඩීඑල් ක්‍රියාවන් ඒකාබද්ධ කරන භාවිතා කළ හැකිය .org.hibernate.tool.schema.Action Enum

නමුත් , ඔබට DataSourceමෙය සමඟ ක්‍රමලේඛනගතව වින්‍යාසගත කළ නොහැක . මෙය ඒකාබද්ධව භාවිතා කිරීම වඩා හොඳ org.hibernate.cfg.AvailableSettings#HBM2DDL_AUTOනමුත් වර්තමාන කේතය Stringවටිනාකමක් අපේක්ෂා කරයි (උපුටා ගැනීම උපුටා ගත් SessionFactoryBuilderImpl):

this.schemaAutoTooling = SchemaAutoTooling.interpret( (String) configurationSettings.get( AvailableSettings.HBM2DDL_AUTO ) );

… සහ enumදෙකෙහිම අභ්‍යන්තර අගයන් org.hibernate.boot.SchemaAutoToolingසහ org.hibernate.tool.schema.Actionඒවා ප්‍රසිද්ධියේ නිරාවරණය නොවේ.

මෙහි දී, නියැදි ක්‍රමලේඛන DataSourceවින්‍යාසය (මගේ වසන්ත ඇරඹුම් යෙදුම්වල භාවිතා වේ) එය සූදුවට ස්තූතිවන්ත වන .name().toLowerCase()නමුත් එය ක්‍රියා කරන්නේ ඉරකින් තොරව අගයන් සමඟ පමණි ( create-dropනිදසුනක් ලෙස නොවේ ):

@Bean(name = ENTITY_MANAGER_NAME)
public LocalContainerEntityManagerFactoryBean internalEntityManagerFactory(
        EntityManagerFactoryBuilder builder,
        @Qualifier(DATA_SOURCE_NAME) DataSource internalDataSource) {

    Map<String, Object> properties = new HashMap<>();
    properties.put(AvailableSettings.HBM2DDL_AUTO, SchemaAutoTooling.CREATE.name().toLowerCase());
    properties.put(AvailableSettings.DIALECT, H2Dialect.class.getName());

    return builder
            .dataSource(internalDataSource)
            .packages(JpaModelsScanEntry.class, Jsr310JpaConverters.class)
            .persistenceUnit(PERSISTENCE_UNIT_NAME)
            .properties(properties)
            .build();
}

0

පෙරනිමි අගය සොයන්නේ කාටද ...

එය වසන්ත-ඇරඹුමේ 2.0.5 අනුවාදයේ සහ 1.1.0 JpaProperties හි ප්‍රභව කේතයේ ලියා ඇත:

    /**
     * DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto"
     * property. Defaults to "create-drop" when using an embedded database and no
     * schema manager was detected. Otherwise, defaults to "none".
     */
    private String ddlAuto;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.