java - OneToOne 使用 Hibernate 和 Spring 数据创建查询

标签 java mysql spring hibernate spring-data

我有这部分数据库架构: schema 和这个User实体:

@Entity
@Table(name = "user", catalog = "ats")
public class User implements java.io.Serializable{

    private static final long serialVersionUID = 1L;
    private String username;
    private boolean enabled;
    private Role role;
    @JsonIgnore
    private ClientVersion clientVersion;
    private ClientLicense clientLicense;
    @JsonIgnore
    private Set<NotificationHasUser> notificationHasUsers = new HashSet<NotificationHasUser>(0);

    public User() {
    }

    public User(String username, boolean enabled) {
        this.username = username;
        this.enabled = enabled;
    }

    public User(String username, boolean enabled, Role role, Set<NotificationHasUser> notificationHasUsers) {
        this.username = username;
        this.enabled = enabled;
        this.role = role;
        this.notificationHasUsers = notificationHasUsers;
    }

    @Id
    @Column(name = "username", unique = true, nullable = false, length = 45)
    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Column(name = "enabled", nullable = false)
    public boolean isEnabled() {
        return this.enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_role", nullable = false)
    public Role getRole() {
        return this.role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_clientVersion", nullable = false)
    public ClientVersion getClientVersion() {
        return this.clientVersion;
    }

    public void setClientVersion(ClientVersion clientVersion) {
        this.clientVersion = clientVersion;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user")
    public Set<NotificationHasUser> getNotificationHasUser() {
        return this.notificationHasUsers;
    }

    public void setNotificationHasUser(Set<NotificationHasUser> notificationHasUsers) {
        this.notificationHasUsers = notificationHasUsers;
    }

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
    public ClientLicense getClientLicense(){
        return this.clientLicense;
    }

    public void setClientLicense(ClientLicense clientLicense){
        this.clientLicense = clientLicense;
    }
}

这是我的 ClientLicense 实体

@Entity
@Table(name = "clientlicense", catalog = "ats")
public class ClientLicense implements java.io.Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer idClientLicense;
    private Date startDate;
    private Date endDate;
    private int counter;
    private String macAddress;
    private String cpuId;
    private User user;

        public ClientLicense() {
        }

        /**
         * @param startDate
         * @param endDate
         * @param counter
         * @param macAddress
         * @param cpuId
         * @param users
         */
        public ClientLicense(Date startDate, Date endDate, int counter, String macAddress, String cpuId, User user) {
            super();
            this.startDate = startDate;
            this.endDate = endDate;
            this.counter = counter;
            this.setMacAddress(macAddress);
            this.setCpuId(cpuId);
            this.user = user;
        }

        @Id
        @GeneratedValue(strategy = IDENTITY)
        @Column(name = "id_clientLicense", unique = true, nullable = false)
        public Integer getIdClientLicense() {
            return this.idClientLicense;
        }

        public void setIdClientLicense(Integer idClientLicense) {
            this.idClientLicense = idClientLicense;
        }


        @Column(name = "startDate", nullable = false)
        public Date getStartDate() {
            return this.startDate;
        }

        public void setStartDate(Date startDate) {
            this.startDate = startDate;
        }

        @Column(name = "endDate", nullable = false)
        public Date getEndDate() {
            return this.endDate;
        }

        public void setEndDate(Date endDate) {
            this.endDate = endDate;
        }


        @Column(name = "counter", nullable = false)
        public int getCounter() {
            return this.counter;
        }

        public void setCounter(int counter) {
            this.counter = counter;
        }   

        /**
         * @return the macAddress
         */
        @Column(name = "macAddress", nullable = false)
        public String getMacAddress() {
            return macAddress;
        }

        /**
         * @param macAddress the macAddress to set
         */
        public void setMacAddress(String macAddress) {
            this.macAddress = macAddress;
        }

        /**
         * @return the cpuId
         */
        @Column(name = "cpuId", nullable = false)
        public String getCpuId() {
            return cpuId;
        }

        /**
         * @param cpuId the cpuId to set
         */
        public void setCpuId(String cpuId) {
            this.cpuId = cpuId;
        }

        @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
        @JoinColumn(name = "id_username")
        public User getUser() {
            return this.user;
        }

        public void setUser(User user) {
            this.user = user;
        }
    }

当我尝试添加新的客户端许可证时,我收到 key 用户名已存在,即使它不存在。 例如,如果我有这个用户表:

username    enabled id_role id_clientVersion
luca        1       1       1
roberto     1       4       1

以及此客户端许可证:

id_clientLicense startDate  endDate     counter macAddress cpuId   id_username
1                2016-01-29 2017-01-29  300     12587.3645 658cPI  luca

我尝试使用 id_username roberto 添加客户端许可证,但它不起作用,并出现以下错误

Duplicate entry 'roberto' for key 'PRIMARY' 

这个来自java,使用mySQL工作台我可以添加roberto和luca更多次。显然,我想添加一次用户以尊重一对一的关系。 错误出在这个隐藏查询上,自动创建:

insert 
    into
        ats.user
        (id_clientVersion, enabled, id_role, username) 
    values
        (?, ?, ?, ?)

但我只打过电话

@Override
    public ClientLicense createClientLicense(ClientLicense clientLicense) {
        return clientLicenseServices.create(clientLicense);
    }

通过这段代码:

License license = new License();
license.setCounter(clientLicenseForm.getCounter());
license.setCpuId(clientLicenseForm.getCpuId());
license.setStartDate(clientLicenseForm.getStartDate());
license.setEndDate(clientLicenseForm.getEndDate());
license.setMacAddress("macAddress");

//Store license into database 
ClientLicense clientLicense;
try{
    clientLicense = new ClientLicense();
    clientLicense.setCounter(clientLicenseForm.getCounter());
    clientLicense.setCpuId(clientLicenseForm.getCpuId());
    clientLicense.setEndDate(clientLicenseForm.getEndDate());
    clientLicense.setStartDate(clientLicenseForm.getStartDate());
    clientLicense.setMacAddress(clientLicenseForm.getMacAddress());
    clientLicense.setUser(databaseAdministrationServices.findById(clientLicenseForm.getUser()));
    databaseAdministrationServices.createClientLicense(clientLicense);
}catch(Exception e){
    throw new QueryException(e);
}

为什么它会尝试创建新用户?

最佳答案

隐藏查询的原因是这里的CascadeType.ALL:

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "id_username")
    public User getUser() {
        return this.user;
    }

您可以从这些类型中选择合适的类型。 JPA 级联类型

Java持久化架构支持的级联类型如下:

CascadeType.PERSIST :表示 save() 或 persist() 操作级联到相关实体。
CascadeType.MERGE :表示当所属实体合并时,相关实体也合并为托管状态。
CascadeType.REFRESH :对刷新()操作执行相同的操作。 CascadeType.REMOVE:删除拥有实体时,删除与此设置关联的所有相关实体。
CascadeType.DETACH:如果发生“手动分离”,则分离所有相关实体。
CascadeType.ALL:是上述所有级联操作的简写。

关于java - OneToOne 使用 Hibernate 和 Spring 数据创建查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35125577/

相关文章:

java - 在 Java 6 上验证回历日期(伊斯兰历)

php - 如何在 laravel 4.2 中按类型和日期顺序列出数据库中的数据?

mysql - 创建一个在 MYSQL 中起作用的函数

MySQL加入多对多单行

java - maven 和 spring 应用程序部署错误 : Unable to locate NamespaceHandler for namespace [http://www. springframework.org/schema/context]

java - 如何在 spring 单元测试中快速模拟服务?

java - 如果在 springboot 的结果中合并/组合,缓存方法(使用咖啡因)是否可能返回部分响应?

java - out.write 运行多次但结果文件为空

java - 如何正确使用MapStruct @Mapping和@Mappings?

java - 如何在不重新启动 Web 应用程序的情况下重新加载 servlet 类?