æåŸã«ãWebãããžã§ã¯ããéå§ããããã«æçããŸããã å¿
èŠãªãœãŒã¹ããã¿ã¹ã¯ãéçŽããå¥ã®todoãããŒãžã£ãŒã ããã¯éã®ããã®ãããžã§ã¯ããšããŠèšç»ãããã®ã§ããšãŠããããã§æ£ããã ã¢ãŒããã¯ãã£ãšãã¯ãããžãŒã«åŠ¥åã¯ãããŸããã ãã¹ããã©ã¯ãã£ã¹ã®ã¿ãããŒãã³ã¢ã®ã¿ã ãããŠããã¡ãããããã¯ãã¹ãŠããæ°ã«å
¥ãã®Intellij IDEAã«ãããããã·ã¥ããã€ããã§ããã
Javaã7幎éïŒæåŸã®2ã€ã¯Scalaãšæ··åïŒããŠãããGroovyãè©Šãããã£ãã®ã§ãã çµã¿ç«ãŠã«ã¯ãã¡ãããGradleã人æ°ããã䟿å©ã§ãã ã¬ãŒã«ã¯ããŸãã«ããããã¯ããããŠããããã«èŠããã®ã§ã
Spring Bootã䜿çšããŠãWebã«Springã䜿çšããããšã«ããŸããã ãããŠããã¹ãŠãçŽ æŽããããORMãããŸããããªãã£ãã ãã§ãã è·å Žã§ã¯ãã客æ§ãå人çã«å«ãHibernateãèŠãŠïŒç¬ããªãã§ãã ãã-å¥ã®è©±ã§ãïŒããããç§ãã¡ã®èªè»¢è»ã«çœ®ãæããŸããã ãã¬ãã£ããªçµéšãšã2ã3ã®ãšã³ãã£ãã£ã®ã¢ã³ã¹ã¿ãŒãåŒã£åŒµããããªããšããã®ã¯ãä»äºãããŸãã-äŒæ¢ç¶æ
ã¯é£ããã§ãïŒ ç§ã¯å®å
šã«ç°ãªããã®ãè©ŠããŠã¿ããã£ãã å¶ç¶ãéžã°ãã
Ebeanã«åºäŒããŸããã
æçµçãªã¹ã¿ãã¯ã®éžæåŸãäœæ¥ã沞隰ãå§ããŸããã ããããæ®å¿µãªãããæ©èœãåããã«ãŒãã¯ãŸã ãŸã æ©èœããŠããŸããã ãã£ããã®äžã§ããã®çç±ã®èª å®ãªèšãèš³ã
ãšããŒã³
ç§ã®æèŠã§ã¯ããã®ãªãŒãã³ãœãŒã¹ORMãã¬ãŒã ã¯ãŒã¯ã¯ãå€å
žçãªJPAå®è£
ãå«ã人ã«ãã£ãŠäœæããããã®ã§ãæµè¡ã«ææãªäººã«å¥œãããŠããŸãã äž»ãªæ©èœïŒ
- 䜿ãæ
£ãããããã³ã°ïŒjava.persistenceã¢ãããŒã·ã§ã³ã䜿çšïŒ;
- ã·ã³ãã«ãªAPI;
- ã»ããã¢ãããç°¡åã
- æè»ãªãã§ããé¢é£ãšã³ãã£ãã£ã
- éšåãµã³ããªã³ã°;
- å€æŽã®è¿œè·¡ã
- ã»ãã·ã§ã³ã®äžè¶³;
- ãã€ãã£ããã©ã³ã¶ã¯ã·ã§ã³ã®ãµããŒã
- éåæããŒãã
- ãªãŒããã¥ãŒãã³ã°ãïŒ
ã€ãŸããéåžžã®éãšã³ã¿ãŒãã©ã€ãºWebã¢ããªã±ãŒã·ã§ã³ã«å¿
èŠãªãã¹ãŠã®ãã®ã§ãã ãã¬ãŒã ã¯ãŒã¯ã®äœæè
ã¯éæ¹ããªãä»äºãããŸããã Playã®éåžžã®ORMã®1ã€ãšããŠè¿œå ãããã®ã¯ãäœã®çç±ããªãã£ããšæããŸãïŒ æåã¯ã
ãµã€ããäœããã®åœ¢ã§äžååã«æŽæ°ãããéçºãåçµããããšãæããŠã
ãŸã ã ãã ããGitHubã«ã¯
avaje-ebeanorm 4.xã®éåžžã«æ°ããããŒãžã§ã³ã
ãããŸã ã ãããŠãã³ãã¥ããã£ãšPlayã®äººæ°ã®ãããã§ããããžã§ã¯ãã®éçºã¯ç¶ç¶ããŠããŸãã githubã§ã®ã¢ã¯ãã£ããã£ã®èšŒæ ãšããŠïŒ

Ebeanã§ã®åºæ¬çãªã¯ãšãªã®äŸã次ã«ç€ºããŸãã
ãšã³ãã£ãã£ã®äœæãä¿åãæŽæ°ïŒ
Order order = new Order(); order.setOrderDate(new Date()); ...
éšåãªããžã§ã¯ããæäœããïŒ
äŸã«çæ³ãåŸãŠãææ°ã®ã¢ã¯ãã£ãã«ãµããŒããããŠããããŒãžã§ã³4.1.8ã䜿çšãããšããæçµæ±ºå®ãäžãããŸããã éå¿ã build.gradleã«äŸåé¢ä¿ãè¿œå ããŸãã
compile('org.avaje.ebeanorm:avaje-ebeanorm:4.1.8')
äœæãããæ§æïŒ
@Configuration @PropertySource("config/db.properties") class EbeanConfig { @Autowired DbConfig dbConfig @Bean EbeanServer ebeanServer() { EbeanServerFactory.create(serverConfig()) } ServerConfig serverConfig() { new ServerConfig( dataSourceConfig: dataSourceConfig(), name: "main", ddlGenerate: false, ddlRun: false, defaultServer: true, register: true, namingConvention: new MatchingNamingConvention() ) } DataSourceConfig dataSourceConfig() { new DataSourceConfig(driver: dbConfig.driver, username: dbConfig.username, password: dbConfig.password, url: dbConfig.url) } }
ãããŠããã¹ããšã³ãã£ãã£ïŒ
@Entity class TestEntity { @Id UUID id Integer value }
ç§ã¯ãã§ã«çã®æããå©çãèŠè¶ããŠæãããããŸããã ããã... ...ããšã話ã¯ãããŸããããã¡ããã
java.lang.IllegalStateExceptionïŒBeanã¯ã©ã¹xxxTestEntityã¯æ¡åŒµãããŠããŸããã§ããã ãæåã¯ãã¹ãŠãèœã¡ãŸãã
ãïŒéåžžã人ã¯äœãã倱æããå Žåã«ã®ã¿ããã¥ã¡ã³ããèªã¿ãŸãã ãããŠããã¯ããã«è¯ãããšã§ãã Ebeanã®éåžžã®æäœã§ã¯ãã¢ã»ã³ããªæ®µéã§.classãã¡ã€ã«ã®ãã€ãã³ãŒããå±éããå¿
èŠãããããšãããããŸãã ã³ã³ãã€ã«çŽåŸã ãªããããå¿
èŠãªã®ã§ããïŒ ã»ãšãã©ãã¹ãŠã®ORMã¯ã¯ã©ã¹ã«åã蟌ãŸããŠããŸããããããã®ã»ãšãã©ã¯åçŽã«ç°ãªãæ¹æ³ã§ãããããŠããŸãã ããšãã°ãHibernateã¯
cglibãä»ããŠã©ã³ã¿ã€ã ãããã·ãäœæããLazyã³ã¬ã¯ã·ã§ã³ãžã®ã¢ã¯ã»ã¹ãã€ã³ã¿ãŒã»ããããŸãã éæã§æ£çŽãªæ ãè
ã¯ããã®ãããªãããã³ã°ãªãã§ã¯å®è¡ã§ããŸããã Ebeanã¯ãå
šå¡ãšãšãã«ãé
延èªã¿èŸŒã¿ãšéšåãªããžã§ã¯ãããµããŒãããä¿åæäœäžã«ãµãŒããŒã«äžèŠãªããŒã¿ãéä¿¡ããªãããã«åãã£ãŒã«ãã®å€æŽã远跡ããŸãã
ã©ã€ãã©ãªã®åæããŒãžã§ã³ã¯ããããã·ãžã®2ã€ã®ã¢ãããŒãããµããŒãããŠããŸãããClassLoaderãä»ããŠããŒããããšãã«.classãã¡ã€ã«ã«ããããé©çšããã¯ã©ã¹ã³ãŒããã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ããŸãïŒJVMã®éå§æã«ãšãŒãžã§ã³ããæ¥ç¶ããå¿
èŠããããŸããïŒã æéãçµã€ã«ã€ããŠããµããŒãã容æã«ããããã«ãæåã®ãªãã·ã§ã³ã®ã¿ãæ®ããŸããã
ããŒã...é£ããã§ããã...人ã
ã¯ã©ããããããPlayãã¬ãŒã ã¯ãŒã¯ã§Ebeanãšäžç·ã«äœãã§ããŸããïŒ ORMèªäœã«ã¯ãã³ã³ãã€ã«ããã.classãã¡ã€ã«ã®ãã€ãã³ãŒããå±éã§ãã
ebeanorm-agentã©ã€ãã©ãªãšãPlayãæ£åžžã«äœ¿çšããSBTããããæ£åžžã«äœ¿çšã§ããã©ã€ãã©ãªãä»å±ããŠããŸãã Playã§ã®ã³ãŒãã®ãã«ãã¯å
éšã®ã¿ã§ããããããã¹ãŠãæèšã®ããã«æ©èœããŸãã ãããŠã誰ãããããèå°è£ã§äœãèµ·ãã£ãŠããã®ãæšæž¬ããŸããã
ã°ã©ãã«
ãããã質åã¯ãGradleã«ãã®ãããªæ©èœã¯ãããŸããïŒ Mavençšã®ãã©ã°ã€ã³ã¯ééããªããããŸãã ããããGradleã«ãšã£ãŠã¯ããŸã£ããäœãèŠã€ãããŸããã§ããïŒãã¶ãç§ã¯èŠèŠããã£ãã§ãïŒã æåã¯åæºãããã®ãã³ãã£ãŒãèŸããããšããèããŸãã...ããããæåŸã®ç¬éã«ç§ã¯éãŸããåé¡ãçµããããªãããšã決ããŸããã
ã ãããäžè¶³ããŠãããã©ââã°ã€ã³ãäœæããŠãã ããïŒ
Gradleã«ç¬èªã®ãã«ãããŒã«ãè¿œå ããæã䟿å©ãªæ¹æ³ã¯ããããžã§ã¯ãã«ãŒããã£ã¬ã¯ããªã«
buildSrcã¢ãžã¥ãŒã«ãäœæãã
ããšã§ãã ãã®ã¢ãžã¥ãŒã«ã®ã³ãŒãã¯ãä»ã®ãã¹ãŠã®ãã«ãã¹ã¯ãªããã§èªåçã«äœ¿çšå¯èœã«ãªããŸãïŒãã¹ãŠã®ãªãã·ã§ã³ã«ã€ããŠã¯ã
ããã§èª¬æã
ãŸã ïŒã
次ã«ã
buildSrcãã£ã¬ã¯ããªå
ã«build.gradleãäœæããŸãã
apply plugin: 'groovy' repositories { mavenCentral() } dependencies {
buildSrcã¢ãããŒãã§ã¯ãã©ã°ã€ã³ãäœæããå¿
èŠã¯ãããŸãããïŒGroovyã¹ã¯ãªããããã³ãŒããèšè¿°ããŠåŒã³åºãããšãã§ããŸãïŒãGradle APIãæ¡åŒµããããšã§æ£ããæ¹æ³ãå®è¡ããŸãã çµå±ã®ãšããã確ãã«ãåŸã§ããã¹ãŠãå®æåãšããŠæŽçããäžè¬çãªäœ¿çšã®ããã«ã©ããã«é
眮ããããšæãã§ãããã
ãã©ã°ã€ã³ã®äž»ãªã¢ã€ãã¢ã¯ãJavaãGroovyããŸãã¯Scalaãã³ã³ãã€ã«ããå段éã®åŸã«Ebeanã䜿çšããã³ã³ãã€ã©ãŒã«ãã£ãŠäœæããããã¡ã€ã«ãèŠã€ããŠåŠçããããšã§ãã ãã®åé¡ã¯ããããã次ã®ããã«è§£æ±ºãããŸãã
class EbeanPlugin implements Plugin<Project> {
ããã«ãããã¯ãšãã¹ãã³ããŒèªäœæ¬¡ç¬¬ã§ãã ã¢ã«ãŽãªãºã ã¯éåžžã«åçŽã§ããæåã«ããã£ã«ã¿ãŒã«é©ããããŒã¹ãã£ã¬ã¯ããªå
ã®ãã¹ãŠã®.classãã¡ã€ã«ãååž°çã«åéãã次ã«ããããããšãŒãžã§ã³ããã«æž¡ããŸãã åŠçèªäœã¯ç°¡åã§ããå
¥åã¹ããªãŒã ããåŠçããããã®ã©ãããŒãã«ããŒã ãã§ãªãããšã³ãã£ãã£ããããŸãã äž¡æ¹ãäœæããŠãªã³ã¯ããåŸã¯ããã¡ã€ã«ãéããŠãã©ã³ã¹ãã©ãŒã ïŒ...ïŒãåŒã³åºãã ãã§ãåæã«çºçããå¯èœæ§ã®ãããšã©ãŒããã£ããããŸãã ã¢ã»ã³ããªå
ã®ãã¹ãŠã¯æ¬¡ã®ããã«ãªããŸãã
class EBeanEnhancer { private final Path classPath private final FileFilter fileFilter EBeanEnhancer(Path classPath) { this(classPath, { file -> true }) } EBeanEnhancer(Path classPath, FileFilter fileFilter) { this.classPath = classPath this.fileFilter = fileFilter } void enhance() { collectClassFiles(classPath.toFile()).each { classFile -> if (fileFilter.accept(classFile)) { enhanceClassFile(classFile); } } } private void enhanceClassFile(File classFile) { def transformer = new Transformer(new FileSystemClassBytesReader(classPath), "debug=" + 1);
ãã£ã«ã¿ãŒã®äœææ¹æ³ã¯ã衚瀺ïŒãŸãã¯æ¥ããããïŒããŠãæå³ããããŸããã ä»»æã®java.io.FileFilterã€ã³ã¿ãŒãã§ãŒã¹å®è£
ã䜿çšã§ããŸãã å®éããã®æ©èœã¯ãªãã·ã§ã³ã§ãã
FileSystemClassBytesReaderã¯å¥ã®åé¡ã§ãã ããã¯ããã»ã¹ã®éåžžã«éèŠãªèŠçŽ ã§ãã ãã©ã³ã¹ãã©ãŒããŒã§å¿
èŠãªå Žåãé¢é£ãã.classãã¡ã€ã«ãèªã¿åããŸãã ããšãã°ããµãã¯ã©ã¹ãåæããããšãebean-agentã¯ClassBytesReaderãä»ããŠã¹ãŒããŒã¯ã©ã¹ã«@MappedSuperclassã¢ãããŒã·ã§ã³ã®ååšã確èªããããèŠæ±ããŸãã ãã
ããªããšjava.lang.IllegalStateExceptionïŒBeanã¯ã©ã¹xxxSubClassEntityã¯æ¡åŒµãããŸãããïŒ ããããããšãªãé£ã³åºããŸãã
class FileSystemClassBytesReader implements ClassBytesReader { private final Path basePath; FileSystemClassBytesReader(Path basePath) { this.basePath = basePath; } @Override byte[] getClassBytes(String className, ClassLoader classLoader) { def classFilePath = basePath.resolve(className.replace(".", "/") + ".class"); def file = classFilePath.toFile() def buffer = new byte[file.length()] try { file.withInputStream { classFileStream -> classFileStream.read(buffer) } } catch (IOException e) { throw new EbeanEnhancementException("Failed to load class '$className' at base path '$basePath'", e); } buffer } }
çŸããèå¥åãebeanãã§ãã©ã°ã€ã³ãåŒã³åºãã«ã¯ãebean.propertiesãã¡ã€ã«ãbuildSrc / resources / META-INFãã©ã«ããŒã«è¿œå ããå¿
èŠããããŸãã
implementation-class=com.avaje.ebean.gradle.EbeanPlugin
ããã ãã§ã ãã©ã°ã€ã³ã®æºåãã§ããŸããã
æåŸã«ãã¡ã€ã³ãããžã§ã¯ãã®build.gradleã«ãçŽ æŽãããè¡ãè¿œå ããŸãã
apply plugin: 'ebean'
ããã«ã°ã©ãã«ãšã®Ebeanã®æåããç¥äººã®ç©èªããããŸãã ãã¹ãŠãæ£åžžã«æ©èœããŠããŸãã
GitHub
gradle-ebean-enhancerã§ãã©ã°ã€ã³ãããŠã³ããŒãã§ããŸãã æ®å¿µãªãããä»ã®ãšããããã¹ãŠãæªå å·¥ã§ãããã³ãŒããbuildSrcã«ã³ããŒããå¿
èŠããããŸãã è¿ãå°æ¥ãçµäºããŠMaven CentralãšGradleãªããžããªã«éä¿¡ããããã«ããŠãã ããã
IntelliJ Idea
è¯ããã¥ãŒã¹ã¯ ãYevgeny Krasikã®Idea 13ã®
ãã©ã°ã€ã³ãããã圌ã«æè¬ããŠããããšã§ãïŒ ãã©ã°ã€ã³ã¯ãã«ãããã»ã¹ãããªãã¹ã³ãããã³ã³ãã€ã©ãç±å¿ã«è¿œè·¡ããŠã.classãã¡ã€ã«ãå±éããŸãã Ideaèªäœã§Spring Bootã¢ããªã±ãŒã·ã§ã³ãå®è¡ããã³ãããã°ããã«ã¯ããããå¿
èŠã§ããããã¯ãã¯ããã«äŸ¿å©ã§äœ¿ããããããã§ãã
æªããã¥ãŒã¹ïŒãã©ã°ã€ã³ã¯ãå€ãããŒãžã§ã³ã®ãšãŒãžã§ã³ãã©ã€ãã©ãª3.2.2ã§åäœããŸãã 圌女ã®æŽ»åã®ææç©ã¯Ebean 4.xãšã¯äºææ§ããªããæåã¯å¥åŠãªè¡åãèµ·ãããŸãã
解決çïŒ githubã§ãã©ãŒã¯ãäœæããç®çã®ããŒãžã§ã³ã®ãã©ã°ã€ã³ãåæ§ç¯ããŸãã
ãã¹ãŠãæèšä»æãã®ããã«ãªããŸããã ã¢ããªã±ãŒã·ã§ã³ãéå§ãããŸããã ãã¹ããšã³ãã£ãã£ã¯æ°žç¶åããŠããŒãã§ããŸããã
å®éãããã«ã€ããŠæžãããšã¯ã§ããŸããã§ãã...ãããã1ã€ã®ãããããããããŸãã ãšã³ãã£ãã£ã®éå±€ã®æ§ç¯ãéå§ããBaseEntityã@MappedSuperclassãæãã€ãããã
java.lang.IllegalStateExceptionïŒBeanã¯ã©ã¹xxxSubClassEntityã¯æ¡åŒµãããŸãããïŒ ããã§åã³ã
javapã¯ãäœããã®çç±ã§ãã¹ãŠã®ãµãã¯ã©ã¹ãæ¡åŒµãããŠããªãããšã瀺ããŸããã ã©ãããŠïŒ ãªãã§ïŒ
è¿·æãªãšã©ãŒãIDEãã©ã°ã€ã³ã«å¿ã³èŸŒãã ããšãå€æããŸããã çŸåšã®ã¯ã©ã¹ãå±éããããã»ã¹äžã«ããã©ã³ã¹ãã©ãŒããŒã¯ããã€ãã®ããã«ããµãã¯ã©ã¹ãåæããããšããŸãã ãããè¡ãã«ã¯ãClassBytesReaderã®å®è£
ãæäŸããå¿
èŠãããããšãæãåºããŸãã ãã ãããã€ããªããŒã¿ã§ã¯ãªããäœããã®çç±ã§IDEãã©ã°ã€ã³ãå®è£
ãããšãGroovyã®ãœãŒã¹ã³ãŒãããã©ã³ã¹ãã©ãŒããŒã«ãéãããããããè©°ãŸã£ãŠããŸããŸãã
ãã®ããããã©ãŒã¯ã¯éåžžã«åœ¹ç«ã¡ãŸããã ããã¯ïŒ
次ã®ããã«ãªããŸããïŒ
if (virtualFile == null) { compileContext.addMessage(CompilerMessageCategory.ERROR, "Unable to detect source file '" + className + "'. Not found in output directory", null, -1, -1); return null; } final Module fileModule = compileContext.getModuleByFile(virtualFile); final VirtualFile outputDirectory = compileContext.getModuleOutputDirectory(fileModule);
å©çïŒ ãã©ã°ã€ã³ã®äœæè
ãORMãã¬ãŒã ã¯ãŒã¯èªäœã®å€ãã䜿çšããªãã£ãããšãèªããŸãã ããããç§ãäžæºãèšãããšãã§ããå¯äžã®ããšã¯ãå¥å
šãªãšã©ãŒã¡ãã»ãŒãžã®æ¬ åŠã§ãã çµå±ã®ãšãããéãã«æ©èœããªã補åã芳å¯ããããšã¯äœãšãªãæ²ããããšã§ãã
å®å
šã§ä¿®æ£ããããã©ã°ã€ã³ã³ãŒãã¯ãå·çæç¹ã§GitHubã®å¯äžã®
idea-ebean-enhancerãã©ãŒã¯ã«ãããŸãã ã€ã³ã¹ããŒã«ã®æºåãã§ããŠããzipãžã®ãªã³ã¯ããããŸãã
ãŸãšã
IntelliJ IdeaãŠãŒã¶ãŒã¯ã€ãã«ãææ°ããŒãžã§ã³ã®EbeanããµããŒãããå®å
šã«æ©èœãããã©ã°ã€ã³ãæã«å
¥ããŸããã
Mavenãšãšãã«ãGradleã¯ãã®ORMãã¬ãŒã ã¯ãŒã¯ããµããŒãããæ¡åŒµæ©èœãååŸããŸããã
ç§ã®éãèªè
ããã®
Ebeanãã©ããªç£ã§ããããè©Šãåæ°ãå©ããããšãé¡ã£ãŠããŸãã çµå±ã®ãšããããã®ãã¹ã«æ²¿ã£ããã¹ãŠã®éèŠãªé害ãå
æãããããã§ãã ããŠããŸãã¯å°ãªããšãããã¯ããªãã«åæ§ã®éãé²ã¿ãããã€ãã®ãªãã¿ã®ãªãã©ã€ãã©ãªã®å
éšãæãäžããããšãåºæ¿ããã§ãããã
ãŸããã³ãŒãã®èšè¿°ã«ãããæéã¯ããã®åºçç©ãæºåããããã倧å¹
ã«çãããšããç§ã«ãšã£ãŠã¯ããªãé¢çœããã«æããŸããã