hibernate - spring-data-jpa @OneToMany fails with lazy init -
i trying create parent-child relationship using spring-data-jpa, hibernate, spring-data, h2 (for tesitng), , postgress (production).
here tables defined in h2.sql:
create table if not exists menu ( menuid bigint(11) not null auto_increment, displaytext varchar (100) default not null, displayorder int default null ); create table if not exists menuitem ( menuitemid bigint(11) not null auto_increment, displaytext varchar (100) default not null, path varchar (50) null, tooltip varchar (500) default not null, displayorder int default null, calltype varchar (50) default not null );
i have 2 simple entities:
@entity public class menu { @id @generatedvalue(strategy = generationtype.auto) private long menuid; @onetomany(fetch = fetchtype.lazy, mappedby = "menu") private list<menuitem> menuitems = new arraylist<menuitem>(); private string displaytext; private int displayorder;
and
@entity public class menuitem { @id @generatedvalue(strategy = generationtype.auto) private long menuitemid; private string displaytext; private string path; private string tooltip; private int displayorder; @manytoone(fetch = fetchtype.lazy) @joincolumn(name = "menuid", nullable = false) private menu menu; @enumerated(enumtype.string) @column(name = "calltype", nullable = false) private httptype calltype;
i have application:
@configuration @componentscan @enablejparepositories @enabletransactionmanagement @enableautoconfiguration public class application { public static void main(string[] args) { applicationcontext myapplication = springapplication.run( application.class, args ); } }
and configuration class:
@configuration public class myconfiguration { @bean public localcontainerentitymanagerfactorybean entitymanagerfactory(datasource datasource, jpavendoradapter jpavendoradapter) { localcontainerentitymanagerfactorybean lef = new localcontainerentitymanagerfactorybean(); lef.setdatasource( datasource ); lef.setjpavendoradapter( jpavendoradapter ); lef.setpackagestoscan( "com.xxx.yyy" ); return lef; } @bean public jpavendoradapter jpavendoradapter() { hibernatejpavendoradapter hibernatejpavendoradapter = new hibernatejpavendoradapter(); hibernatejpavendoradapter.setshowsql( true ); hibernatejpavendoradapter.setgenerateddl( true ); hibernatejpavendoradapter.setdatabase( database.h2 ); return hibernatejpavendoradapter; } @bean public platformtransactionmanager transactionmanager() { return new jpatransactionmanager(); } @bean public datasource datasource() { return new embeddeddatabasebuilder().settype( embeddeddatabasetype.h2 ).setname( "product" ) .addscript( "classpath:h2.sql" ).build(); } }
i have test:
@springapplicationconfiguration @transactional class menurepositorytest extends specification { @shared configurableapplicationcontext context @shared private menurepository menurepository void setupspec() { future future = executors.newsinglethreadexecutor().submit( new callable() { @override public configurableapplicationcontext call() throws exception { return (configurableapplicationcontext) springapplication.run(application.class) } }) context = future.get(60, timeunit.seconds) menurepository = context.getbean(menurepository.class) } void cleanupspec() { if (context != null) { context.close() } } @transactional def "test creating single menu single menuitem"() { def menu = new menu() menu.setdisplayorder(0) menu.setdisplaytext("test") menurepository.save(menu) def menuitem = new menuitem() menuitem.settooltip("tooltip 1") menuitem.setpath("/1") menuitem.setcalltype(httptype.get) menuitem.setdisplaytext("tooltip") menu.addmenuitem(menuitem) when: def menus = menurepository.findall() menus[0].getmenuitems() then: menus[0].getmenuitems().size() == 1 } }
here gradle showing dependencies:
apply plugin: 'java' apply plugin: 'groovy' apply plugin: 'idea' apply plugin: 'spring-boot' apply plugin: 'jacoco' apply plugin: 'war' apply plugin: 'maven' buildscript { repositories { maven { url "http://repo.spring.io/libs-snapshot" } mavenlocal() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.0.0.rc4") } } repositories { mavencentral() maven { url "http://repo.spring.io/libs-snapshot" } maven { url 'http://repo.spring.io/milestone' } } dependencies { compile("org.springframework.boot:spring-boot-starter-web:1.0.0.release") compile("org.springframework.boot:spring-boot-starter-data-jpa:1.0.1.release") compile("org.springframework.boot:spring-boot:1.0.1.release") compile("org.springframework:spring-orm:4.0.0.rc1") compile("org.hibernate:hibernate-entitymanager:4.2.1.final") compile("org.springframework:spring-tx") compile("com.h2database:h2:1.3.172") compile("joda-time:joda-time:2.3") compile("org.thymeleaf:thymeleaf-spring4") compile("org.codehaus.groovy.modules.http-builder:http-builder:0.7.1") compile('org.codehaus.groovy:groovy-all:2.2.1') compile('org.jadira.usertype:usertype.jodatime:2.0.1') testcompile('org.spockframework:spock-core:0.7-groovy-2.0') { exclude group: 'org.codehaus.groovy', module: 'groovy-all' } testcompile('org.codehaus.groovy.modules.http-builder:http-builder:0.7+') testcompile("junit:junit") } jacocotestreport { group = "reporting" description = "generate jacoco coverage reports after running tests." } sourcesets { main { java { srcdirs = [] } groovy { srcdirs = ['src/main/groovy', 'src/main/java'] } resources { srcdirs = ['src/main/resources'] } output.resourcesdir = "build/classes/main" } test { java { srcdirs = [] } groovy { srcdirs = ['src/test/groovy', 'src/test/java'] } resources { srcdirs = ['src/test/resources'] } output.resourcesdir = "build/classes/test" } } task wrapper(type: wrapper) { gradleversion = '1.11' }
answer:
change build.gradle use different spock
buildscript { repositories { maven { url "http://repo.spring.io/libs-milestone" } mavenlocal() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.0.1.release") } } repositories { mavencentral() maven { url "http://repo.spring.io/libs-milestone" } maven { url "https://repository.jboss.org/nexus/content/repositories/releases" } maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } maven { url "http://repo.spring.io/snapshot" } maven { url 'http://repo.spring.io/milestone' } } dependencies { compile("org.springframework.boot:spring-boot-starter-web:1.0..release") compile("org.springframework.boot:spring-boot:1.0.1.release") compile("org.springframework.boot:spring-boot-starter-data-jpa:1.0.1.release") testcompile('org.spockframework:spock-core:1.0-groovy-2.0-snapshot') { exclude group: 'org.codehaus.groovy', module: 'groovy-all' } testcompile('org.spockframework:spock-spring:1.0-groovy-2.0-snapshot') { exclude group: 'org.spockframework', module: 'spock-core' exclude group: 'org.spockframework', module: 'spring-beans' exclude group: 'org.spockframework', module: 'spring-test' exclude group: 'org.codehaus.groovy', module: 'groovy-all' } testcompile('org.springframework:spring-test:4.0.3.release') ...}
change test not use setupspec or @shared:
@contextconfiguration(classes = myapplication, loader = springapplicationcontextloader) @transactional class menurepositorytest extends specification { @autowired private menurepository menurepository def "test creating single menu single menuitem"() { def menu = new menu() menu.setdisplayorder(0) menu.setdisplaytext("test") menurepository.save(menu) def menuitem = new menuitem() menuitem.settooltip("tooltip 1") menuitem.setpath("/1") menuitem.setcalltype(httptype.get) menuitem.setdisplaytext("tooltip") menu.addmenuitem(menuitem) when: def menus = menurepository.findall() menus[0].getmenuitems() then: menus[0].getmenuitems().size() == 1 } }
the answer problem lies spock , spring integration. mappings correct, spock , spring weren't playing nicely together. updated question show correct way run integration test.
Comments
Post a Comment