Spring-Hibernate自引用表

时间:2013-05-16 13:10:34

标签: java spring hibernate

假设我有Category表,每个类别都有父类和子类。但是父级是可选的,因此它可能没有父级。

CREATE TABLE `Category` (
  `categoryID` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `parentCategoryID` int(11) DEFAULT NULL,
  PRIMARY KEY (`categoryID`),
  KEY `category_category_fk` (`parentCategoryID`),
  CONSTRAINT `category_category_fk` FOREIGN KEY (`parentCategoryID`) REFERENCES `Category` (`categoryID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

这是hbm文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated May 16, 2013 12:50:14 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="model.Category" table="Category">
        <id name="categoryId" type="java.lang.Integer">
            <column name="categoryID" />
            <generator class="identity" />
        </id>
        <many-to-one name="parentCategory" class="model.Category" fetch="select" cascade="all">
            <column name="parentCategoryID" />
        </many-to-one>
        <property name="name" type="string">
            <column name="name" length="100" />
        </property>
        <set name="subCategories" table="Category" inverse="true" lazy="true" fetch="select">
            <key>
                <column name="parentCategoryID" />
            </key>
            <one-to-many class="model.Category" />
        </set>
    </class>
</hibernate-mapping>

我使用Hibernate Tools来生成HBM和DAO。

现在的问题是,每当我试图坚持Category没有父级时,Hibernate在表格中添加了两行,每一行都设置为NULL,第二个是我放置的值和parentCategoryID引用的第一行。

如果我认为它与cascade选项有关,但是每次删除它时,Java都会抛出异常,例如.... references an unsaved transient instance - save the transient instane before flushing

任何人都知道如何在这里正确地做到这一点?我上周刚刚开始学习Spring-Hibernate,所以这对我来说很新鲜。提前谢谢。

修改(相关代码)

model.Category

/**
 * Category generated by hbm2java
 * model.Category
 */
 @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="categoryId")
 public class Category implements java.io.Serializable {

private Integer categoryId;

private Category parentCategory;

private String name;

@JsonIgnore
private Set<Category> subCategories = new HashSet<Category>(0);

public Category() {
}

public Category(Category parentCategory,
        String name
        Set<Category> subCategories) {
    this.parentCategory = parentCategory;
    this.name = name;
    this.subCategories = subCategories;
}

public Integer getCategoryId() {
    return this.categoryId;
}

public void setCategoryId(Integer categoryId) {
    this.categoryId = categoryId;
}

public Category getParentCategory() {
    return this.parentCategory;
}

public void setParentCategory(Category parentCategory) {
    this.parentCategory = parentCategory;
}

public String getName() {
    return this.name;
}

public void setName(String name) {
    this.name = name;
}

public Set<Category> getSubCategories() {
    return this.subCategories;
}

public void setSubCategories(Set<Category> subCategories) {
    this.subCategories = subCategories;
}

}

dao.CategoriesDao

/**
 * Home object for domain model class Category.
 * @see model.Category
 * @author Hibernate Tools
 */
@Repository
public class CategoriesDao {

    private static final Log log = LogFactory.getLog(CategoriesDao.class);

    @Autowired
    private SessionFactory sessionFactory;

    public void persist(Category transientInstance) {
        log.debug("persisting Category instance");
        try {
            sessionFactory.getCurrentSession().persist(transientInstance);
            log.debug("persist successful");
        } catch (RuntimeException re) {
            log.error("persist failed", re);
            throw re;
        }
    }

    public void attachDirty(Category instance) {
        log.debug("attaching dirty Category instance");
        try {
            sessionFactory.getCurrentSession().saveOrUpdate(instance);
            log.debug("attach successful");
        } catch (RuntimeException re) {
            log.error("attach failed", re);
            throw re;
        }
    }

    public void attachClean(Category instance) {
        log.debug("attaching clean Category instance");
        try {
            sessionFactory.getCurrentSession().lock(instance, LockMode.NONE);
            log.debug("attach successful");
        } catch (RuntimeException re) {
            log.error("attach failed", re);
            throw re;
        }
    }

    public void delete(Category persistentInstance) {
        log.debug("deleting Category instance");
        try {
            sessionFactory.getCurrentSession().delete(persistentInstance);
            log.debug("delete successful");
        } catch (RuntimeException re) {
            log.error("delete failed", re);
            throw re;
        }
    }

    public Category merge(Category detachedInstance) {
        log.debug("merging Category instance");
        try {
            Category result = (Category) sessionFactory.getCurrentSession()
                    .merge(detachedInstance);
            log.debug("merge successful");
            return result;
        } catch (RuntimeException re) {
            log.error("merge failed", re);
            throw re;
        }
    }

    public Category findById(java.lang.Integer id) {
        log.debug("getting Category instance with id: " + id);
        try {
            Category instance = (Category) sessionFactory
                    .getCurrentSession().get("model.Category", id);
            if (instance == null) {
                log.debug("get successful, no instance found");
            } else {
                log.debug("get successful, instance found");
            }
            return instance;
        } catch (RuntimeException re) {
            log.error("get failed", re);
            throw re;
        }
    }

    public List<Category> findByExample(Category instance) {
        log.debug("finding Category instance by example");
        try {
            List<Category> results = (List<Category>) sessionFactory
                    .getCurrentSession().createCriteria("model.Category")
                    .add(create(instance)).list();
            log.debug("find by example successful, result size: "
                    + results.size());
            return results;
        } catch (RuntimeException re) {
            log.error("find by example failed", re);
            throw re;
        }
    }
}

修改(添加控制器)

controller.AddCategoryController

@Controller
@RequestMapping("/categories/addcategory.*")
public class AddCategoryController {
    @Autowired
    private CategoriesService categoriesService;

    @InitBinder("Category")
    public void initBinder(WebDataBinder binder) {
        binder.setValidator(new CategoryValidator());
        /**
         * Will put NULL for empty string instead of trying to put value
         * so later can be used to NULL empty parentCategory
         */
        binder.registerCustomEditor(Category.class, new StringTrimmerEditor(true));
    }

    @RequestMapping(method = RequestMethod.GET)
    public String view(Model model) {
        this.setFormAttributes(model, new Category());
        return "/categories/addcategory";
    }

    /**
     * Called on form submission
     */
    @RequestMapping(method = RequestMethod.POST)
    public String create(
            @ModelAttribute("Category") @Valid Category category,
            BindingResult result, Model model) {
        if (result.hasErrors()) {
            this.setFormAttributes(model, category);
            return "/categories/addcategory";
        }
        this.categoriesService.save(category);
        return "redirect:/categories/listcategories.htm";
    }

    private void setFormAttributes(Model model, Category category) {
        model.addAttribute("Category", category);
        model.addAttribute("categories", this.categoriesService.listCategories());
    }
}

0 个答案:

没有答案