浅析JPA分类表的操作函数
HOOLOO 人气:0这里说的分类表是指一般系统中用到的分类管理的表。
结构如下:
CREATE TABLE `categories` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `parent_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '父分类ID', `code` varchar(255) NOT NULL DEFAULT '' COMMENT '分类代码', `title` varchar(255) NOT NULL DEFAULT '' COMMENT '分类名称', `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态1启用0禁用', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB;
实体类,如下 :
@Entity @DynamicUpdate @Table(name = "categories") public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private BigInteger id; // 为了设置关联关系,需要注释掉. // 反正这里没搞明白,没设关联关系前,设了Column()返回的数据中字段不对了。 // 这里后面再研究吧 // private BigInteger parent_id; @CreationTimestamp @Column(nullable = false, updatable = false) private Date created_at; @UpdateTimestamp @Column(nullable = false) private Date updated_at; private String title; private String code; private int status; // 中间省略 set get 代码 // 关联关系 @ManyToOne // 查不到记录就忽略 @NotFound(action= NotFoundAction.IGNORE) // 外键是parent_id @JoinColumn(name = "parent_id") private Category parent; public Category getParent() { return parent; } public void setParent(Category p) { this.parent = p; } }
Repository :
public interface CategoryRepository extends JpaRepository<Category, BigInteger>, JpaSpecificationExecutor<Category> { List<Category> findAllByCode(String code); @Query(value = "select * from categories WHERE parent_id=?1 ", nativeQuery = true) List<Category> findAllByParentId(BigInteger pid); @Transactional @Modifying @Query(value="update Category c set c.status=?2 where c.id in ?1") void updateStatusById(List<BigInteger> ids, Integer status); }
下面是Controller:
@RestController @RequestMapping(value = "/api/category") public class CategoryController { private CategoryRepository categoryRepository; public CategoryController(CategoryRepository categoryRepository) { this.categoryRepository = categoryRepository; } @GetMapping(value = "fetch-child") public List<Category> getChildren(@RequestParam(value = "id", required = true, defaultValue = "0") BigInteger id) { return categoryRepository.findAllByParentId(id); } /** * 修改记录 * @param category * @return */ @PostMapping(value = "") public @ResponseBody String store(@RequestBody StoreCategoryData category) { System.out.println(category.toString()); Optional<Category> row = categoryRepository.findById(category.parentId); if (row.isPresent()) { Category p = row.get(); Category c = new Category(); c.setParent(p); c.setTitle(category.title); c.setCode(category.code); categoryRepository.save(c); return "saved"; } throw new RuntimeException("父分类不存在"); } }
StoreCategoryData:
public class StoreCategoryData { public String title; public String code; public BigInteger parentId; }
这个类是为了新建记录时用的。别问为什么,我自己研究出来的,因为我不知道还有其它什么好办法。
1,前端需要一个列表,显示:父类名称 +当前分类的信息。
由于记录中只有一个parent_id来关联父分类,所以用sql的写法就是写个left join就好了。把要查的查出来。这种事交给php那是非常简单。
Java不行啊,尤其是JPA。
查了查文档,设置关联关系可能是比较优雅的方式。
所以,有了实体类中的@ManyToOne的注释,因为加了这个属性,原先的parent_id字段就得隐藏。这里太明白为什么,留待以后研究。
加了关联注释之后,再查询,程序会自动把这个关联的数据给查出来,一并返回给前端。我这里做的是Restful接口。
2,新建记录的时候,要设置parent_id值。可是加了关联关系后,parent_id字段就消失了,没办法直接给这个字段赋值。也就没办法直接保存。
百度了半天也没找到解决办法。(说句题外话,现在网上的文章重复的太多,抄来抄去)
于是耍点小聪明,多建了一个与表单提交的数据格式对应的类,强类型语言跟弱类型语言比,就是麻烦好多。好处就是严谨。用这个类来接收提交的数据。
再从中取得父分类的ID,去查一遍父分类,如果存在,就new一个父分类的实例出来,set到新记录的Parent属性里。
这时候现用这个数据去保存,jpa会帮你自动给parent_id赋上值。
绕了一大圈。
3,实体类中加了关联关系之后,repository中定义一个查询,根据父ID,但其下的子分类。
这里自定义了一个方法:findAllByParentId
这里用了ParentId,不知道对不对,更不知道后面会有什么样的影响。
不管了,能用就行。
我这代码虽然能起作用,可不一定正确。仅供参考!
加载全部内容