java - Hibernate Spring bi directional many to many removal not working -
i having issue while trying conduct deletion in many-to-many relationship. first of i'd mention story. have 2 entity classes called post , category, here posts associated categories, , true other way around. can create categories , post, , when creating or editing post can associate categories no problem. issue arises when remove category post. there no exception or error thrown, not remove it.
normally see below code, in post set, when remove category object , save object, hibernate take care of removing regarding relation in shared table, not happen!
other that, i've tried multiple solutions, did not quite work out either.
- https://forum.hibernate.org/viewtopic.php?f=1&t=17
- hibernate bidirectional manytomany delete issue 3.http://www.codereye.com/2009/06/hibernate-bi-directional-many-to-many.html 4.hibernate bi-directional many many association creates duplicates 5.https://howtoprogramwithjava.com/hibernate-manytomany-unidirectional-bidirectional/
post entity
@entity @table(name = "posts") public class post { @id @column(name = "postid") @generatedvalue(strategy = generationtype.auto) private long postid; @column(name = "posttitle") private string posttitle; @column(name = "postcontext") @type(type = "text") private string postcontext; @column(name = "posteddate") private date posteddate; @column(name = "visitcount") private long visitcount; @column(name = "publishable") private boolean publishable; @manytomany(cascade = {cascadetype.persist, cascadetype.merge}, targetentity = category.class, fetch = fetchtype.eager) //@manytomany(cascade = {cascadetype.persist, cascadetype.merge}, fetch = fetchtype.eager,mappedby = "posts") @jointable(name = "post_category", joincolumns = {@joincolumn(name = "postid")}, inversejoincolumns = {@joincolumn(name = "categoryid")}) private set<category> categories = new hashset<>(); @onetoone(cascade = cascadetype.all) private user user; public post() { } public post(string posttitle, string postcontext, date posteddate, boolean publishable, set<category> categories, user user) { this.posttitle = posttitle; this.postcontext = postcontext; this.posteddate = posteddate; this.publishable = publishable; this.categories = categories; this.user = user; } public long getpostid() { return postid; } public void setpostid(long postid) { this.postid = postid; } public string getposttitle() { return posttitle; } public void setposttitle(string posttitle) { this.posttitle = posttitle; } public string getpostcontext() { return postcontext; } public void setpostcontext(string postcontext) { this.postcontext = postcontext; } public date getposteddate() { return posteddate; } public long getvisitcount() { return visitcount; } public void setvisitcount(long visitcount) { this.visitcount = visitcount; } public void setposteddate(date posteddate) { this.posteddate = posteddate; } public boolean ispublishable() { return publishable; } public void setpublishable(boolean publishable) { this.publishable = publishable; } public set<category> getcategories() { return categories; } public void setcategories(set<category> categories) { this.categories = categories; } public user getuser() { return user; } public void setuser(user user) { this.user = user; } }
category entity
@entity @table(name = "categories") public class category { @id @column(name = "categoryid") @generatedvalue(strategy = generationtype.auto) private long categoryid; @column(name = "categoryname") private string categoryname; @column(name = "createddate") private date createddate; @manytoone @joincolumn(name = "parent_category_id") private category parentcategory; @onetomany(mappedby = "parentcategory", cascade = cascadetype.all, fetch = fetchtype.eager) public set<category> subcategories = new hashset<>(); // @manytomany(cascade = {cascadetype.persist, cascadetype.merge}, fetch = fetchtype.eager, targetentity = post.class) // @jointable(name = "post_category", joincolumns = {@joincolumn(name = "categoryid")}, inversejoincolumns = {@joincolumn(name = "postid")}) @manytomany(cascade = {cascadetype.persist, cascadetype.merge}, fetch = fetchtype.eager,mappedby = "categories") private set<post> posts = new hashset<>(); public category() { } public category(string categoryname) { this.categoryname = categoryname; } public category(string categoryname, date createddate, category parentcategory) { this.categoryname = categoryname; this.createddate = createddate; this.parentcategory = parentcategory; this.subcategories = new hashset<>(); if (parentcategory != null) { parentcategory.subcategories.add(this); } } public set<post> getposts() { return posts; } public void setposts(set<post> posts) { this.posts = posts; } public long getcategoryid() { return categoryid; } public void setcategoryid(long categoryid) { this.categoryid = categoryid; } public string getcategoryname() { return categoryname; } public void setcategoryname(string categoryname) { this.categoryname = categoryname; } public date getcreateddate() { return createddate; } public void setcreateddate(date createddate) { this.createddate = createddate; } public category getparentcategory() { return parentcategory; } public void setparentcategory(category parentcategory) { this.parentcategory = parentcategory; } public set<category> getsubcategories() { return subcategories; } public void setsubcategories(set<category> subcategories) { this.subcategories = subcategories; } }
test
@test public void stage09_editcreatedposttest() { //fetch post post post = appservice.getpostbyname(postname); //fetch child category; category category = appservice.getcategorybyname(childcatname); //remove child category post.getcategories().remove(category); //selected child category not null assertnotnull(category); appservice.editpost(post); //fetch post again post post2 = appservice.getpostbyname(postname); //check post2 object not null assertnotnull(post2); //check category size assertequals(1, post2.getcategories().size()); }
edit post edit dao method
public void editpost(post post) { session session = sessionfactory.opensession(); transaction transaction = session.begintransaction(); try { session.update(post); transaction.commit(); } catch (hibernateexception e) { system.err.println(e); transaction.rollback(); } { session.close(); } }
update
for couple of days, i've been googling , checking out different sources , i've decided test entire structure , entity classes in non j2ee environments using hibernate , eclipselink jpa without spring. i've come realize while using application in spring container, issue still continues, without spring environment, surprisingly there no such issue @ all. tests work fine, bi directional many many annotation i've been dwelling on getting work.
i'd hereby share spring configuration , maven pom configuration observation , suggestions do. briefly manage transactions on hibernate's side. if see gap or wrong i'll appreciate help!
thanks again
applicationcontext.xml
<?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:property-placeholder location="classpath:hibernate.properties"/> <!-- hibernate connection configuration --> <bean id="datasource" class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname" value="${orm.connection.driver_class}"/> <property name="url" value="${orm.connection.url}"/> <property name="username" value="${orm.connection.username}"/> <property name="password" value="${orm.connection.password}"/> </bean> <!-- hibernate configuration settings --> <bean id="sessionfactory" class="org.springframework.orm.hibernate4.localsessionfactorybean"> <property name="datasource" ref="datasource"/> <property name="packagestoscan" value="com.tugrulaslan.entity"/> <property name="hibernateproperties"> <props> <prop key="hibernate.dialect">${orm.dialect}</prop> <prop key="hibernate.show_sql">${orm.show_sql}</prop> <prop key="hibernate.hbm2ddl.auto">${orm.hbm2ddl.auto}</prop> <!-- --> <prop key="current_session_context_class">thread</prop> </props> </property> </bean> <!-- hibernate session factory creation <bean id="transactionmanager" class="org.springframework.orm.hibernate4.hibernatetransactionmanager"> <property name="sessionfactory" ref="sessionfactory"/> </bean> <tx:annotation-driven transaction-manager="transactionmanager"/> --> <context:component-scan base-package="com.tugrulaslan"/> </beans>
pom.xml http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 com.tugrulaslan webapp war 1.0-snapshot blogwebapp maven webapp http://maven.apache.org
<properties> <project-java.version>1.7</project-java.version> <maven-compiler-plugin.version>3.1</maven-compiler-plugin.version> <junit.version>4.11</junit.version> <mysql-connector.version>5.1.34</mysql-connector.version> <hibernate.version>4.3.6.final</hibernate.version> <javax-persistance-api.version>1.0.2</javax-persistance-api.version> <spring.version>4.0.6.release</spring.version> </properties> <dependencies> <dependency> <groupid>junit</groupid> <artifactid>junit</artifactid> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <version>${mysql-connector.version}</version> </dependency> <dependency> <groupid>org.hibernate</groupid> <artifactid>hibernate-core</artifactid> <version>${hibernate.version}</version> </dependency> <dependency> <groupid>javax.persistence</groupid> <artifactid>persistence-api</artifactid> <version>${javax-persistance-api.version}</version> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-context</artifactid> <version>${spring.version}</version> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-orm</artifactid> <version>${spring.version}</version> </dependency> <!-- <dependency> <groupid>org.springframework</groupid> <artifactid>spring-tx</artifactid> <version>${spring.version}</version> </dependency>--> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-test</artifactid> <version>${spring.version}</version> </dependency> </dependencies> <build> <finalname>blogwebapp</finalname> <plugins> <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <version>${maven-compiler-plugin.version}</version> <configuration> <source>${project-java.version}</source> <target>${project-java.version}</target> </configuration> </plugin> </plugins> </build>
in service check if committing after delete below
session.gettransaction().commit();
Comments
Post a Comment