浅析JPA分类表的操作函数
这里说的分类表是指一般系统中用到的分类管理的表。
结构如下:
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);
}
@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,不知道对不对,更不知道后面会有什么样的影响。
不管了,能用就行。
我这代码虽然能起作用,可不一定正确。仅供参考!
到此这篇关于浅析JPA分类表的操作函数的文章就介绍到这了,更多相关JPA分类表内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
相关文章