Java-Hibernate的严重问题:查询列表时自动添加记录

我正在使用-Hibernate 4-Spring 3

我遇到一个我无法理解的问题:当我尝试在Hibernate中检索对象列表时,数据库的另一个表中充满了行.我怀疑我设置的“ CASCADE”和“ FETCHING”属性有些错误,但是我真的不明白.

让我解释一下这个问题.

这里有4个实体:

>具有所有凭据的用户,例如用户名,isEnabled,Authorities List和类似内容
>记录用户角色的授权
>一个ProfiledUser,其中包含与配置文件数据,地址数据以及检查列表有关的所有内容,最后
>包含一些数据和用户参考的检查

我试图建模以下

这是课程:用户

@Entity
@Table(name="USERS")
@Inheritance(strategy=InheritanceType.JOINED)
public class User implements UserDetails,DomainObject {

    private static final long serialVersionUID = 1L;
    private long id;
    //other stuff here
    Set<Authority> authorities = new HashSet<Authority>();

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id",unique=true,nullable=false)
    public long getId() {
        return id;
    }

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

    @ElementCollection(fetch=FetchType.EAGER)
    @JoinTable(name="AUTHORITIES",joinColumns=@JoinColumn(name="user_id"))
    public Set<Authority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(Set<Authority> authorities) {
        this.authorities = authorities;
    }   
}

用户简介

@Entity
@Table(name="PROFILED_USERS")
public class ProfiledUser extends User{

    private static final long serialVersionUID = 1L;
    //other stuff here. Everything with CASCADE ALL
    private Collection<Checkup> checkupMap = new HashSet<Checkup>();

    public ProfiledUser() {
        super();
        // TODO Auto-generated constructor stub
    }

    @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
    public Collection<Checkup> getCheckupMap() {
        return checkupMap;
    }

    public void setCheckupMap(Collection<Checkup> checkupMap) {
        this.checkupMap = checkupMap;
    }
}

检查

@Entity
@Table(name="CHECKUPS")
public class Checkup implements DomainObject{

    private long id;
    private ProfiledUser profiledUser;
    //other stuff here everyithing fetched EAGERLY
    private boolean pending = true;

    public Checkup() {
        super();
    }

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id")
    public long getId() {
        return id;
    }

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

    @OneToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="profiledUser")
    public ProfiledUser getProfiledUser() {
        return profiledUser;
    }

    public void setProfiledUser(ProfiledUser profiledUser) {
        this.profiledUser = profiledUser;
    }

    @Column(name="pending")
    public boolean isPending() {
        return pending;
    }

    public void setPending(boolean pending) {
        this.pending = pending;
    }
}

最后是权威

@Embeddable
public class Authority implements GrantedAuthority{

    private static final long serialVersionUID = 1L;
    private String authority;  //Spring Security demands them to start with "ROLE_"

    public Authority() {
        super();
    }

    @Column(name="authority")
    public String getAuthority() {
        return this.authority;
    }

    //the administer is the one allowed to change the users' role
    @RolesAllowed("ROLE_ADMIN")
    public void setAuthority(String authority) {
        if(!authority.startsWith("ROLE_"))
            authority= (new String("ROLE_")).concat(authority.toUpperCase());
        this.authority = authority.toUpperCase();
    }
}

现在的问题.当我尝试检索PENDING核对清单(pending是Checkup的布尔属性)时,执行以下操作

@SuppressWarnings("unchecked")
@Override
public List<Checkup> loadPendingCheckups()
{
    Session session = sessionFactory.getCurrentSession();
    Query query = session.createQuery("from " + objName + " where pending is true");
    List<Checkup> checkupList = query.list();
    if(checkupList.isEmpty())
        return null;
    else
        return checkupList;
}

此方法来自CheckupDaoImpl,该方法用@Transactional注释.

Hibernate开始从Authority表中删除并添加大量行.例如,它从用户2删除角色ROLE_USER并添加两次,以便用户2的ROLE_USER数量随时间增加一倍:1、2、4、8、16、32、64等.
我真的不明白为什么要求SELECT会以WRITE操作结束!
请帮助我,因为我真的不知道问题出在哪里!

编辑:

当我调用loadPendingCheckups()时,我可以在控制台中阅读以下内容:

Hibernate: select checkup0_.id as id0_,checkup0_.date as date0_,checkup0_.ending_measurement as ending6_0_,checkup0_.mid_measurement as mid7_0_,checkup0_.pending as pending0_,checkup0_.physiology as physiology0_,checkup0_.profiledUser as profiled9_0_,checkup0_.quiet_measurement as quiet10_0_,checkup0_.maxTrainingFrequency as maxTrain4_0_,checkup0_.minTrainingFrequency as minTrain5_0_,checkup0_.scale_outcome as scale11_0_ from CHECKUPS checkup0_ where checkup0_.pending=1
Hibernate: select measuremen0_.id as id1_0_,measuremen0_.average_pressure as average2_1_0_,measuremen0_.diastolic_pressure as diastolic3_1_0_,measuremen0_.heart_rate as heart4_1_0_,measuremen0_.spO2 as spO5_1_0_,measuremen0_.systolic_pressure as systolic6_1_0_ from MEASUREMENTS measuremen0_ where measuremen0_.id=?
Hibernate: select measuremen0_.id as id1_0_,measuremen0_.systolic_pressure as systolic6_1_0_ from MEASUREMENTS measuremen0_ where measuremen0_.id=?
Hibernate: select physiology0_.id as id2_0_,physiology0_.height as height2_0_,physiology0_.morphism_type as morphism3_2_0_,physiology0_.structure_type as structure4_2_0_,physiology0_.weight as weight2_0_ from PHYSIOLOGIES physiology0_ where physiology0_.id=?
Hibernate: select profiledus0_.id as id7_9_,profiledus0_1_.account_non_expired as account2_7_9_,profiledus0_1_.account_non_locked as account3_7_9_,profiledus0_1_.credentials_non_expired as credenti4_7_9_,profiledus0_1_.enabled as enabled7_9_,profiledus0_1_.password as password7_9_,profiledus0_1_.username as username7_9_,profiledus0_.address_data as address3_8_9_,profiledus0_.contact_data as contact4_8_9_,profiledus0_.personal_data as personal5_8_9_,profiledus0_.subscription_date as subscrip1_8_9_,authoritie1_.user_id as user1_7_11_,authoritie1_.authority as authority11_,addressdat2_.id as id4_0_,addressdat2_.country as country4_0_,addressdat2_.location as location4_0_,addressdat2_.street as street4_0_,addressdat2_.street_number as street5_4_0_,addressdat2_.zip_code as zip6_4_0_,checkupmap3_.profiledUser as profiled9_7_12_,checkupmap3_.id as id12_,checkupmap3_.id as id0_1_,checkupmap3_.date as date0_1_,checkupmap3_.ending_measurement as ending6_0_1_,checkupmap3_.mid_measurement as mid7_0_1_,checkupmap3_.pending as pending0_1_,checkupmap3_.physiology as physiology0_1_,checkupmap3_.profiledUser as profiled9_0_1_,checkupmap3_.quiet_measurement as quiet10_0_1_,checkupmap3_.maxTrainingFrequency as maxTrain4_0_1_,checkupmap3_.minTrainingFrequency as minTrain5_0_1_,checkupmap3_.scale_outcome as scale11_0_1_,measuremen4_.id as id1_2_,measuremen4_.average_pressure as average2_1_2_,measuremen4_.diastolic_pressure as diastolic3_1_2_,measuremen4_.heart_rate as heart4_1_2_,measuremen4_.spO2 as spO5_1_2_,measuremen4_.systolic_pressure as systolic6_1_2_,measuremen5_.id as id1_3_,measuremen5_.average_pressure as average2_1_3_,measuremen5_.diastolic_pressure as diastolic3_1_3_,measuremen5_.heart_rate as heart4_1_3_,measuremen5_.spO2 as spO5_1_3_,measuremen5_.systolic_pressure as systolic6_1_3_,physiology6_.id as id2_4_,physiology6_.height as height2_4_,physiology6_.morphism_type as morphism3_2_4_,physiology6_.structure_type as structure4_2_4_,physiology6_.weight as weight2_4_,measuremen7_.id as id1_5_,measuremen7_.average_pressure as average2_1_5_,measuremen7_.diastolic_pressure as diastolic3_1_5_,measuremen7_.heart_rate as heart4_1_5_,measuremen7_.spO2 as spO5_1_5_,measuremen7_.systolic_pressure as systolic6_1_5_,scaleoutco8_.id as id3_6_,scaleoutco8_.bmr as bmr3_6_,scaleoutco8_.body_fat as body3_3_6_,scaleoutco8_.metabolic_age as metabolic4_3_6_,scaleoutco8_.muscle_mass as muscle5_3_6_,scaleoutco8_.skeletal_mass as skeletal6_3_6_,scaleoutco8_.visceral_fat as visceral7_3_6_,scaleoutco8_.water as water3_6_,scaleoutco8_.weight as weight3_6_,contactdat9_.id as id5_7_,contactdat9_.email as email5_7_,contactdat9_.mobile as mobile5_7_,contactdat9_.phone as phone5_7_,personalda10_.id as id6_8_,personalda10_.birth_date as birth2_6_8_,personalda10_.name as name6_8_,personalda10_.second_name as second4_6_8_ from PROFILED_USERS profiledus0_ inner join USERS profiledus0_1_ on profiledus0_.id=profiledus0_1_.id left outer join AUTHORITIES authoritie1_ on profiledus0_.id=authoritie1_.user_id left outer join ADDRESS_DATA addressdat2_ on profiledus0_.address_data=addressdat2_.id left outer join CHECKUPS checkupmap3_ on profiledus0_.id=checkupmap3_.profiledUser left outer join MEASUREMENTS measuremen4_ on checkupmap3_.ending_measurement=measuremen4_.id left outer join MEASUREMENTS measuremen5_ on checkupmap3_.mid_measurement=measuremen5_.id left outer join PHYSIOLOGIES physiology6_ on checkupmap3_.physiology=physiology6_.id left outer join MEASUREMENTS measuremen7_ on checkupmap3_.quiet_measurement=measuremen7_.id left outer join SCALE_OUTCOMES scaleoutco8_ on checkupmap3_.scale_outcome=scaleoutco8_.id left outer join CONTACT_DATA contactdat9_ on profiledus0_.contact_data=contactdat9_.id left outer join PERSONAL_DATA personalda10_ on profiledus0_.personal_data=personalda10_.id where profiledus0_.id=?
Hibernate: select measuremen0_.id as id1_0_,personalda10_.second_name as second4_6_8_ from PROFILED_USERS profiledus0_ inner join USERS profiledus0_1_ on profiledus0_.id=profiledus0_1_.id left outer join AUTHORITIES authoritie1_ on profiledus0_.id=authoritie1_.user_id left outer join ADDRESS_DATA addressdat2_ on profiledus0_.address_data=addressdat2_.id left outer join CHECKUPS checkupmap3_ on profiledus0_.id=checkupmap3_.profiledUser left outer join MEASUREMENTS measuremen4_ on checkupmap3_.ending_measurement=measuremen4_.id left outer join MEASUREMENTS measuremen5_ on checkupmap3_.mid_measurement=measuremen5_.id left outer join PHYSIOLOGIES physiology6_ on checkupmap3_.physiology=physiology6_.id left outer join MEASUREMENTS measuremen7_ on checkupmap3_.quiet_measurement=measuremen7_.id left outer join SCALE_OUTCOMES scaleoutco8_ on checkupmap3_.scale_outcome=scaleoutco8_.id left outer join CONTACT_DATA contactdat9_ on profiledus0_.contact_data=contactdat9_.id left outer join PERSONAL_DATA personalda10_ on profiledus0_.personal_data=personalda10_.id where profiledus0_.id=?
Hibernate: delete from AUTHORITIES where user_id=? and authority=?
Hibernate: insert into AUTHORITIES (user_id,authority) values (?,?)
Hibernate: delete from AUTHORITIES where user_id=? and authority=?
...// a very lot of these
Hibernate: insert into AUTHORITIES (user_id,?)
Hibernate: insert into AUTHORITIES (user_id,?)
//a very lot of these

生理,测量等是检查的内容.我认为可以找回.但此后,它会触发大规模删除和删除操作.插入AUTHORITY表中.

编辑2:
看来问题已解决,将表单@ElementCollection切换为用户与授权之间的@OneToMany关系.幸运的是,我正在设计数据库,并且允许我进行此修改.这个问题似乎消失了,但是我仍然没有弄清楚ORM异常行为背后的原因.
更确切地说,最奇怪的是,当我要求从db Hibernate检索Checkups表单时,触发了不可思议的

>删除授权项
>插入授权项

如果有人能指出这一点,将不胜感激.

最佳答案
我不确定这是造成您问题的原因,但是您在ProfiledUser和Checkup之间的双向关系配置不正确.

双向一对多关系配置如下:

>一侧标有@ManyToOne,另一侧标有@OneToMany
> @OneToMany必须具有一个指向对应的@ManyToOne属性的mappingBy属性
>物理映射注释(@JoinColumn)应该在@ManyToOne一侧

像这样:

public class ProfiledUser extends User{
    @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy = "profiledUser")
    public Collection<Checkup> getCheckupMap() {
        return checkupMap;
    }
    ...
}

public class Checkup implements DomainObject {
    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="profiledUser")
    public ProfiledUser getProfiledUser() {
        return profiledUser;
    }
    ...
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原理介绍,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。传统事务中回滚点的使...
今天小编给大家分享的是一文解析spring中事务的传播机制,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获...
这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区别,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。Spring Cloud Netfli...
本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。第一步:整合pom文件,在S...
本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。List 坑列表 = new ArrayList(2);...
这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓存的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇...
本篇内容主要讲解“Spring中的@Autowired和@Resource注解怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学...
今天小编给大家分享一下SpringSecurity怎么定义多个过滤器链的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家
这篇文章主要介绍“Spring的@Conditional注解怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring的@Con...
这篇文章主要介绍了SpringCloudGateway的熔断限流怎么配置的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringCloud&nb...
今天小编给大家分享一下怎么使用Spring解决循环依赖问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考
这篇文章主要介绍“Spring事务及传播机制的原理及应用方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Sp...
这篇“SpringCloudAlibaba框架实例应用分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价
本篇内容主要讲解“SpringBoot中怎么使用SpringMVC”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习...
这篇文章主要介绍“SpringMVC适配器模式作用范围是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringMVC
这篇“导入SpringCloud依赖失败如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要讲解了“SpringMVC核心DispatcherServlet处理流程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来
今天小编给大家分享一下SpringMVCHttpMessageConverter消息转换器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以...
这篇文章主要介绍“Spring框架实现依赖注入的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring框架...
本篇内容介绍了“Spring单元测试控制Bean注入的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下