[{"data":1,"prerenderedAt":265},["ShallowReactive",2],{"slug-content-en-\u002Fprojects\u002Fkinobe":3},{"kind":4,"item":5,"categories":105},"project",{"id":6,"title":7,"body":8,"dateEnd":85,"dateStart":86,"description":87,"extension":88,"featuredInCv":89,"link":90,"meta":91,"navigation":92,"path":93,"repo":94,"seo":95,"stem":96,"tags":97,"__hash__":104},"projects_en\u002Fprojects\u002Fkinobe.md","kinoBE",{"type":9,"value":10,"toc":80},"minimark",[11,16,20,43,46,77],[12,13,15],"h2",{"id":14},"about-the-project","About the Project",[17,18,19],"p",{},"kinoBE (\"Kino Backend\") is the server side of a cinema booking system I built during my IHK vocational training. The centerpiece of the project is a small, hand-written ORM that I implemented from scratch to understand how frameworks like Doctrine or Hibernate map objects to a relational database internally.",[17,21,22,23,27,28,31,32,35,36,31,39,42],{},"Entities are plain Java classes annotated with a custom ",[24,25,26],"code",{},"@Entity",", ",[24,29,30],{},"@Column"," and ",[24,33,34],{},"@Id",", while ",[24,37,38],{},"@OneToManyRelation",[24,40,41],{},"@ManyToOneRelation"," describe the associations between them. At runtime the ORM resolves these annotations via reflection to build SQL, hydrate objects from result sets, and load related entities through their repositories.",[17,44,45],{},"On top of that it reimplements several patterns found in production ORMs:",[47,48,49,67,70],"ul",{},[50,51,52,53,56,57,27,60,31,63,66],"li",{},"a repository layer (",[24,54,55],{},"AbstractRepository\u003CT>",") providing ",[24,58,59],{},"findAll",[24,61,62],{},"findBy",[24,64,65],{},"getById",",",[50,68,69],{},"an identity map that caches already-loaded entities to avoid duplicate objects and redundant queries,",[50,71,72,73,76],{},"and rudimentary dirty checking, where each entity remembers its initial state via a hash so that ",[24,74,75],{},"flush()"," only persists records that actually changed.",[17,78,79],{},"The data is stored in SQLite through JDBC, and the application exposes a REST API (movies, presentations, reservations) for the matching frontend. The build is handled by Maven with a GitHub Actions workflow.",{"title":81,"searchDepth":82,"depth":82,"links":83},"",2,[84],{"id":14,"depth":82,"text":15},"2022-03","2022-02","A hand-written, annotation-driven ORM and REST backend for a cinema booking system, built during my IHK training.","md",false,null,{},true,"\u002Fprojects\u002Fkinobe","https:\u002F\u002Fgithub.com\u002FLinusTebbe\u002FkinoBE",{"title":7,"description":87},"projects\u002Fkinobe",[98,99,100,101,102,103],"java","sqlite","sql","rest","git","cicd","makcFqLv9tjZh8sc7oOzE6WF77BMBfUxXq7igkZf6r8",[106,113,134,161,191,203,214,223],{"name":107,"items":108},"Databases",[109,111],{"slug":100,"name":110},"SQL (MySQL, MariaDB)",{"slug":99,"name":112},"SQLite",{"name":114,"items":115},"Frontend",[116,119,122,125,128,131],{"slug":117,"name":118},"html5","HTML5",{"slug":120,"name":121},"css3","CSS3",{"slug":123,"name":124},"tailwindcss","Tailwind CSS",{"slug":126,"name":127},"bootstrap","Bootstrap",{"slug":129,"name":130},"uikit","UIkit",{"slug":132,"name":133},"extjs","Ext JS",{"name":135,"items":136},"JavaScript Ecosystem",[137,140,143,146,149,152,155,158],{"slug":138,"name":139},"javascript","JavaScript",{"slug":141,"name":142},"typescript","TypeScript",{"slug":144,"name":145},"nodejs","Node.js",{"slug":147,"name":148},"vuejs","Vue.js",{"slug":150,"name":151},"nuxt","Nuxt.JS",{"slug":153,"name":154},"react","React",{"slug":156,"name":157},"next","Next.JS",{"slug":159,"name":160},"deno","Deno",{"name":162,"items":163},"PHP Ecosystem",[164,167,170,173,176,179,182,185,188],{"slug":165,"name":166},"php","PHP",{"slug":168,"name":169},"laravel","Laravel",{"slug":171,"name":172},"symfony","Symfony",{"slug":174,"name":175},"laminas","Laminas",{"slug":177,"name":178},"mezzio","Mezzio",{"slug":180,"name":181},"zend","Zend Framework",{"slug":183,"name":184},"wordpress","WordPress",{"slug":186,"name":187},"shopware","Shopware",{"slug":189,"name":190},"spryker","Spryker",{"name":192,"items":193},"Mobile",[194,197,200],{"slug":195,"name":196},"dart","Dart",{"slug":198,"name":199},"flutter","Flutter",{"slug":201,"name":202},"android","Android",{"name":204,"items":205},"Other Languages",[206,208,211],{"slug":98,"name":207},"Java",{"slug":209,"name":210},"python","Python",{"slug":212,"name":213},"go","Go",{"name":215,"items":216},"Operating Systems",[217,220],{"slug":218,"name":219},"linux","Linux",{"slug":221,"name":222},"windows","Windows",{"name":224,"items":225},"Other",[226,228,231,234,237,240,243,246,249,252,255,258,260,263],{"slug":102,"name":227},"Git",{"slug":229,"name":230},"docker","Docker",{"slug":232,"name":233},"jenkins","Jenkins",{"slug":235,"name":236},"jvm","JVM",{"slug":238,"name":239},"aws","AWS",{"slug":241,"name":242},"cloudflare","Cloudflare",{"slug":244,"name":245},"nginx","Nginx",{"slug":247,"name":248},"redis","Redis",{"slug":250,"name":251},"networking","Networking",{"slug":253,"name":254},"rabbitmq","RabbitMQ",{"slug":256,"name":257},"oidc","OIDC",{"slug":101,"name":259},"REST",{"slug":261,"name":262},"terraform","Terraform",{"slug":103,"name":264},"CI\u002FCD",1783417755291]