<commit_before>
Spring Data Jpa 中级联操作CascadeType的含义
CascadeType.PERSIST

级联新增，保存父对象时会新建其中包含的子对象 

CascadeType.MERGE
级联修改，保存父对象时会更新其中所包含的子对象数据 

CascadeType.REMOVE
级联删除，当删除关联关系时会将子对象的数据删除 

CascadeType.REFRESH
级联刷新，保存关联关系时会更新子对象和数据库中一致
(意思是你在父对象中添加一个只包含ID的子对象，也可以保存进去) 

CascadeType.ALL
包含上述所有操作

fetch 加载方式
立即加载
FetchType.EAGER

懒加载
FetchType.LAZY


SpringDataJpa Specification接口用法
首先，我们需要了解到Specification是springDateJpa中的一个接口，
他是用于当jpa的一些基本CRUD操作的扩展，可以把他理解成一个spring jpa的复杂查询接口。
其次我们需要了解Criteria 查询，这是是一种类型安全和更面向对象的查询。
而Spring Data JPA支持JPA2.0的Criteria查询，相应的接口是JpaSpecificationExecutor。

而JpaSpecificationExecutor这个接口基本是围绕着Specification接口来定义的， Specification接口中只定义了如下一个方法：

Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); 

下面，我们来理解这个方法，首先，要理解这个方法，以及正确的使用它，
就需要对JPA2.0的Criteria查询有一个足够的熟悉和理解，因为这个方法的参数和返回值都是JPA标准里面定义的对象。 

Criteria查询基本概念

Criteria 查询是以元模型的概念为基础的，元模型是为具体持久化单元的受管实体定义的，这些实体可以是实体类，嵌入类或者映射的父类。

CriteriaQuery接口：代表一个specific的顶层查询对象，它包含着查询的各个部分，
比如：select 、from、where、group by、order by等注意：CriteriaQuery对象只对实体类型或嵌入式类型的Criteria查询起作用

Root接口：代表Criteria查询的根对象，Criteria查询的查询根定义了实体类型，能为将来导航获得想要的结果，它与SQL查询中的FROM子句类似

1：Root实例是类型化的，且定义了查询的FROM子句中能够出现的类型。
root代表查询的实体类,query可以从中得到root对象,告诉jpa查询哪一个实体类,
还可以添加查询条件,还可以结合EntityManager对象 得到最终查询的 TypedQuery对象.

2：查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。

3：Criteria查询，可以有多个查询根。 

4.CriteriaBuilder接口：用来构建CritiaQuery的构建器对象Predicate：一个简单或复杂的谓词类型，其实就相当于条件或者是条件组合。 


建表时不使用下划线命名
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

Spring Data JPA是个非常强大的ORM持久化解决方案，免去了mybatis或spring jdbcTemplate的开发人员编写脚本的无趣工作。

通过简单明了地约定好接口方法的规则，来自动生成相应的JPQL语句，映射成PO对象，能大幅节省开发人员的编码量。

接口方法的命名规则也很简单，明白And、Or、Is、Equal、Greater、StartingWith等英文单词的含义，就可以写接口方法了。

以下是从Spring Data JPA官方网站上的docs整理而来，网上其他有些文章写的有的是错的，

大于等于、小于等于应为：GreaterThanEqual、LessThanEqual，而不是GreaterThanEquals、LessThanEquals，如果带了s，会导致程序启动报错。

关键词            |   SQL符号            |样例                                                   | 对应JPQL 语句片段
And              |	  and	              | findByLastnameAndFirstname  |	 … where x.lastname = ?1 and x.firstname = ?2
Or	             |    or	              | findByLastnameOrFirstname   | … where x.lastname = ?1 or x.firstname = ?2
Is,Equals        |    =	                | findByFirstname,findByFirstnameIs,findByFirstnameEquals| … where x.firstname = ?1
Between	         | between xxx and xxx	|findByStartDateBetween	… where x.startDate between ?1 and ?2
LessThan	       |   <	                |findByAgeLessThan	… where x.age < ?1
LessThanEqual	   |<=	findByAgeLessThanEqual	… where x.age <= ?1
GreaterThan	     |>	findByAgeGreaterThan	… where x.age > ?1
GreaterThanEqual |	>=	findByAgeGreaterThanEqual	… where x.age >= ?1
After	>	findByStartDateAfter	… where x.startDate > ?1
Before	<	findByStartDateBefore	… where x.startDate < ?1
IsNull	is null	findByAgeIsNull	… where x.age is null
IsNotNull,NotNull	is not null	findByAge(Is)NotNull	… where x.age not null
Like	like	findByFirstnameLike	… where x.firstname like ?1
NotLike	not like	findByFirstnameNotLike	… where x.firstname not like ?1
StartingWith	like 'xxx%'	findByFirstnameStartingWith	… where x.firstname like ?1(parameter bound with appended %)
EndingWith	like 'xxx%'	findByFirstnameEndingWith	… where x.firstname like ?1(parameter bound with prepended %)
Containing	like '%xxx%'	findByFirstnameContaining	… where x.firstname like ?1(parameter bound wrapped in %)
OrderBy	order by	findByAgeOrderByLastnameDesc	… where x.age = ?1 order by x.lastname desc
Not	<>	findByLastnameNot	… where x.lastname <> ?1
In	in()	findByAgeIn(Collection<Age> ages)	… where x.age in ?1
NotIn	not in()	findByAgeNotIn(Collection<Age> ages)	… where x.age not in ?1
TRUE	=true	findByActiveTrue()	… where x.active = true
FALSE	=false	findByActiveFalse()	… where x.active = false
IgnoreCase	upper(xxx)=upper(yyyy)	findByFirstnameIgnoreCase	… where UPPER(x.firstame) = UPPER(?1)





命名+带分页方式
    Page<ArticleDO> findAllByAccountIdIsAndMenuIdIs(Long menuId, Long accountId, Pageable pageable);<commit_msg>Update springdatajpsAbout.txt<commit_after>
Spring Data Jpa 中级联操作CascadeType的含义
CascadeType.PERSIST

级联新增，保存父对象时会新建其中包含的子对象 

CascadeType.MERGE
级联修改，保存父对象时会更新其中所包含的子对象数据 

CascadeType.REMOVE
级联删除，当删除关联关系时会将子对象的数据删除 

CascadeType.REFRESH
级联刷新，保存关联关系时会更新子对象和数据库中一致
(意思是你在父对象中添加一个只包含ID的子对象，也可以保存进去) 

CascadeType.ALL
包含上述所有操作

fetch 加载方式
立即加载
FetchType.EAGER

懒加载
FetchType.LAZY


SpringDataJpa Specification接口用法
首先，我们需要了解到Specification是springDateJpa中的一个接口，
他是用于当jpa的一些基本CRUD操作的扩展，可以把他理解成一个spring jpa的复杂查询接口。
其次我们需要了解Criteria 查询，这是是一种类型安全和更面向对象的查询。
而Spring Data JPA支持JPA2.0的Criteria查询，相应的接口是JpaSpecificationExecutor。

而JpaSpecificationExecutor这个接口基本是围绕着Specification接口来定义的， Specification接口中只定义了如下一个方法：

Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); 

下面，我们来理解这个方法，首先，要理解这个方法，以及正确的使用它，
就需要对JPA2.0的Criteria查询有一个足够的熟悉和理解，因为这个方法的参数和返回值都是JPA标准里面定义的对象。 

Criteria查询基本概念

Criteria 查询是以元模型的概念为基础的，元模型是为具体持久化单元的受管实体定义的，这些实体可以是实体类，嵌入类或者映射的父类。

CriteriaQuery接口：代表一个specific的顶层查询对象，它包含着查询的各个部分，
比如：select 、from、where、group by、order by等注意：CriteriaQuery对象只对实体类型或嵌入式类型的Criteria查询起作用

Root接口：代表Criteria查询的根对象，Criteria查询的查询根定义了实体类型，能为将来导航获得想要的结果，它与SQL查询中的FROM子句类似

1：Root实例是类型化的，且定义了查询的FROM子句中能够出现的类型。
root代表查询的实体类,query可以从中得到root对象,告诉jpa查询哪一个实体类,
还可以添加查询条件,还可以结合EntityManager对象 得到最终查询的 TypedQuery对象.

2：查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。

3：Criteria查询，可以有多个查询根。 

4.CriteriaBuilder接口：用来构建CritiaQuery的构建器对象Predicate：一个简单或复杂的谓词类型，其实就相当于条件或者是条件组合。 


建表时不使用下划线命名
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

Spring Data JPA是个非常强大的ORM持久化解决方案，免去了mybatis或spring jdbcTemplate的开发人员编写脚本的无趣工作。

通过简单明了地约定好接口方法的规则，来自动生成相应的JPQL语句，映射成PO对象，能大幅节省开发人员的编码量。

接口方法的命名规则也很简单，明白And、Or、Is、Equal、Greater、StartingWith等英文单词的含义，就可以写接口方法了。

以下是从Spring Data JPA官方网站上的docs整理而来，网上其他有些文章写的有的是错的，

大于等于、小于等于应为：GreaterThanEqual、LessThanEqual，而不是GreaterThanEquals、LessThanEquals，如果带了s，会导致程序启动报错。

关键词            |   SQL符号            |样例                                                   | 对应JPQL 语句片段
And              |	  and	              | findByLastnameAndFirstname  |	 … where x.lastname = ?1 and x.firstname = ?2
Or	             |    or	              | findByLastnameOrFirstname   | … where x.lastname = ?1 or x.firstname = ?2
Is,Equals        |    =	                | findByFirstname,findByFirstnameIs,findByFirstnameEquals| … where x.firstname = ?1
Between	         | between xxx and xxx	|findByStartDateBetween	… where x.startDate between ?1 and ?2
LessThan	       |   <	                |findByAgeLessThan	… where x.age < ?1
LessThanEqual	   |<=	findByAgeLessThanEqual	… where x.age <= ?1
GreaterThan	     |>	findByAgeGreaterThan	… where x.age > ?1
GreaterThanEqual |	>=	findByAgeGreaterThanEqual	… where x.age >= ?1
After	>	findByStartDateAfter	… where x.startDate > ?1
Before	<	findByStartDateBefore	… where x.startDate < ?1
IsNull	is null	findByAgeIsNull	… where x.age is null
IsNotNull,NotNull	is not null	findByAge(Is)NotNull	… where x.age not null
Like	like	findByFirstnameLike	… where x.firstname like ?1
NotLike	not like	findByFirstnameNotLike	… where x.firstname not like ?1
StartingWith	like 'xxx%'	findByFirstnameStartingWith	… where x.firstname like ?1(parameter bound with appended %)
EndingWith	like 'xxx%'	findByFirstnameEndingWith	… where x.firstname like ?1(parameter bound with prepended %)
Containing	like '%xxx%'	findByFirstnameContaining	… where x.firstname like ?1(parameter bound wrapped in %)
OrderBy	order by	findByAgeOrderByLastnameDesc	… where x.age = ?1 order by x.lastname desc
Not	<>	findByLastnameNot	… where x.lastname <> ?1
In	in()	findByAgeIn(Collection<Age> ages)	… where x.age in ?1
NotIn	not in()	findByAgeNotIn(Collection<Age> ages)	… where x.age not in ?1
TRUE	=true	findByActiveTrue()	… where x.active = true
FALSE	=false	findByActiveFalse()	… where x.active = false
IgnoreCase	upper(xxx)=upper(yyyy)	findByFirstnameIgnoreCase	… where UPPER(x.firstame) = UPPER(?1)





命名+带分页方式
    Page<ArticleDO> findAllByAccountIdIsAndMenuIdIs(Long menuId, Long accountId, Pageable pageable);

@Entity
@Table(name="menu")
public class MenuDO {
	
	@Id
    private Long id;

	/**
	 * 菜单文本
	 */
	private String text;
	
	private String link;
	
	private Integer level;
	
	private Integer sequence;

	private Long parentId;
	
	@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
	@JoinColumn(name = "parentId")
	private Set<MenuDO> subMenus;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public String getLink() {
		return link;
	}

	public void setLink(String link) {
		this.link = link;
	}

	public Integer getLevel() {
		return level;
	}

	public void setLevel(Integer level) {
		this.level = level;
	}

	public Integer getSequence() {
		return sequence;
	}

	public void setSequence(Integer sequence) {
		this.sequence = sequence;
	}

	public Long getParentId() {
		return parentId;
	}

	public void setParentId(Long parentId) {
		this.parentId = parentId;
	}

	public Set<MenuDO> getSubMenus() {
		return subMenus;
	}

	public void setSubMenus(Set<MenuDO> subMenus) {
		this.subMenus = subMenus;
	}

	public MenuDO() {
		super();
	}

	public MenuDO(Long id, String text, String link, Integer level, Integer sequence, Long parentId) {
		super();
		this.id = id;
		this.text = text;
		this.link = link;
		this.level = level;
		this.sequence = sequence;
		this.parentId = parentId;
	}

    @Override
    public String toString() {
        return "{" +
                "\"id\":" +id.longValue()+
                ", \"text\":\"" + text +
                "\", \"link\":\"" + link  +
                "\",\"level\":" + (level==null?"-1":level.intValue()) +
                ", \"sequence\":" + sequence.intValue() +
                ", \"parentId\":" + (parentId==null?"0":parentId.longValue())+
				", \"subMenus\":" + ((subMenus==null)?"[]":subMenus.toString())+
                "}";
    }
	
	

}




@Entity
@Table(name="article")
public class ArticleDO {
	
	@Id
    private Long id;

    private String title;
    
    private String content;
    
    @JoinColumn(table = "account",name = "id")
    private Long accountId;

    @OneToOne(fetch=FetchType.EAGER)
	@JoinColumn(name = "menuId")
    private MenuDO menu;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public Long getAccountId() {
		return accountId;
	}

	public void setAccountId(Long accountId) {
		this.accountId = accountId;
	}

	public MenuDO getMenu() {
		return menu;
	}

	public void setMenu(MenuDO menu) {
		this.menu = menu;
	}

	public ArticleDO() {
		super();
	}

	public ArticleDO(Long id, String title, String content, Long accountId) {
		super();
		this.id = id;
		this.title = title;
		this.content = content;
		this.accountId = accountId;
	}
    
    @Override
    public String toString() {
        return "{" +
                "\"id\":" + id.longValue() +
                ", \"title\":\"" + title +
                "\", \"content\":\"" + content +
				"\", \"menu\":" + menu.toString() +
                "}";
    }
    

}

{'fraction_non_alphanumeric': 0.09433798664701291, 'fraction_numerical': 0.0055492933321772304, 'mean_word_length': 4.128501556247221, 'pattern_counts': {'":': 14, '<': 32, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6101338', 'n_tokens_mistral': 5227, 'n_tokens_neox': 5352, 'n_words': 866}