Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spring data JPA 笔记 #13

Open
zxy16305 opened this issue Feb 6, 2018 · 3 comments
Open

spring data JPA 笔记 #13

zxy16305 opened this issue Feb 6, 2018 · 3 comments

Comments

@zxy16305
Copy link
Owner

zxy16305 commented Feb 6, 2018

基于 1.11.10.RELEASE (spring boot 1.5.10.RELEASE 所用的版本)


由于上次看文档没有看到复杂查询, 这次再仔细看一遍


书签

@zxy16305 zxy16305 changed the title spring data JPA 文档阅读笔记 spring data JPA 笔记 Feb 20, 2018
@zxy16305
Copy link
Owner Author

zxy16305 commented Feb 20, 2018

实体类中建立一对多、一对一、多对多的关系

在实际的运用中,发现直接在实体类中写父id的话,会使得程序和orm过度耦合(当然带来的是速度的优势)。要使得程序的架构更加明朗,还是得使用hibernate原来那一套。

    //注意注解加到get方法上 一对一多对多也差不多的
    @OneToMany(mappedBy = "parentDept") //这里写持有者对应的属性名
    public Set<OrgMemberEntity> getChildMember() {
        return childMember;
    }

    @ManyToOne()
    @JoinColumn(name = "parent_id")
    @NotFound(action= NotFoundAction.IGNORE)
    @org.hibernate.annotations.ForeignKey(name="none") //据说不会生成外键,不过这是过时的方法
    public OrgDeptEntity getParentDept() {
        return parentDept;
    }

在换成hibernate注解的时候,有一些小问题,记录在这里。

  • 在数据库,有些不存在的父ID可能会写成0,此时匹配父类的的时候会报错。举个例子:
    @ManyToOne
    @JoinColumn(name="dept_id")
    @NotFound(action= NotFoundAction.IGNORE)
    @org.hibernate.annotations.ForeignKey(name="none")
    public OrgDeptEntity getParentDept() {
        return parentDept;
    }

加入 @NotFound 配置未找到的动作就可解决,默认就是报错
(我怀疑spring boot 的配置有解决方案..)

jpa实体类json化嵌套递归的解决方案

这里实在多的一方加上注解`@JsonIgnore`解决( ~~ 具体加在哪边我也不是很懂哈哈哈哈哈 ~~ )
这可能就是门槛吧,要知道怎么解决的甚至还得看源码

jpa的懒加载问题

在开了懒加载配置` @OneToMany(mappedBy = "parentDept",fetch = FetchType.LAZY)`的情况下,会在
查询结果生成代理对象,调用这个代理对象懒加载部分的get方法会报错(~~和我想的有点不一样啊啊~~)

解决的方法一就是关闭懒加载
解决方法二(update 18-3-17): 之前报错是因为session已经提交了(hibernate中的概念),而提交的
原因是因为,没有开启事务...所以在相关方法上加上`@Transactional`就好了。当调用get方法是会自动
查询数据库中的相关信息(好象是一开始只加载id,然后根据调用的方法再加载其他/全部数据)。

jpa update的解决方案

jpa似乎没有原生的update方案(不太确定),一般简单的方式就是先find,修改后save。
但在复杂的状态下代码就太冗余了。
这里是使用@Query注解写jpql语句完成的update操作
 @Modifying
 @Query("update OrgDeptEntity d set d.deptName = :#{#dept.deptName} 
                  where d.id= :#{#dept.id}")
 public int setByDept(@Param("dept") OrgDeptEntity orgDeptEntity);
@Modifying是写入数据库的注释,传入对象则采用@Param的方式,同时在jpql语句中使用 :#{#注解value} 的方式传入(文档上写的不是很明白,这莫非是jpql的用法)

(应该还有其他解决方案的 万能的jpa啊~)

insert or update 的解决方案

读了好几天的文档,查了好几天的资料,都没有比较好的解决方案。仔细一想,就算是mybatis也要发两条sql的,那么jpa先findone,然后再save。这好像也是比较标准的解决方案了。 😂

主键生成策略要指明

出现了一些奇怪的错误,在主键的get方法上加上了 @GeneratedValue(strategy = GenerationType.AUTO) 后解决了问题

关系映射保存的坑

  • 一直爆detached entity passed to persist的错误,网上给出的答案是不要手动设置id。但我的类的id本身就是null,但是第一个部门完好的保存了,结合这个现象,有一个猜想:
    在保存子对象时,再一次保存了父对象(此时的父对象是有id的)。然后把
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    改成
    @ManyToOne
    问题解决。 (没错,hibernate或者说jpa出了问题你都不知道哪里出了问题的。。。)

@zxy16305
Copy link
Owner Author

zxy16305 commented Mar 18, 2018

JPA审计 (JPA Auditing)

当数据写入数据库时,有些数据用程序去确定有些冗余,比如浏览次数、创建时间、修改时间。有些可以通过数据库触发器解决,而比如时间,当数据库所在的环境事件不标准时,会发生一些问题。
JPA提供了审计的功能,链接
例如审计时间的具体的做法时,在相关字段上添加@CreatedDate 、@LastModifiedDate等注解,在实体类上加@EntityListeners(AuditingEntityListener.class)注解。

对标准JPA Entity对象的检查

由于注解加在get方法上,实际检查的get后面的参数,即要求的是标准的getter/setter

@zxy16305
Copy link
Owner Author

zxy16305 commented Mar 27, 2018

FAQ

  • 用persistent.xml生成的entity,却爆出字段名不存在的错误

    查看sql知,他把驼峰式的字段名解析成了下划线形式的字段名。这是hibernate的映射策略问题。

截图:
image

增加配置physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl (让IDE来自动补全吧2333)

  • hibernate_sequence' doesn't exist 的报错
    增加配置
    image

  • nullable的问题
    insert时如有空值,会遇到此类问题,可以在entity类上加上注解

@DynamicInsert
@DynamicUpdate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant