当前位置: 首页 > 知识库问答 >
问题:

无法在一对一关系中更新所属方的属性

呼延德华
2023-03-14

我有一个用户类,每个用户实例都有一个配置文件。个人资料有一个avatarImage属性,我想更新它。我可以在运行时更新用户的字段,但不能更新该用户配置文件的字段。我正在使用springsecurity获取当前用户,我想更新他的avatarImage,但在运行时我得到了一个SQLException。

用户域类:

package com.clinton.kiitsocial

import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

@EqualsAndHashCode(includes='username')
@ToString(includes='username', includeNames=true, includePackage=false)
class User implements Serializable {
private static final long serialVersionUID = 1

transient springSecurityService

//don't touch this...for spring-security
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired

//starting custom domain...can touch this
Integer uniqueId
Date dateCreated
Date lastUpdated

static hasMany = [contents: Content]

static hasOne = [profile: Profile]


User(String username, String password) {
    this()
    this.username = username
    this.password = password
}

Set<Role> getAuthorities() {
    UserRole.findAllByUser(this)*.role
}

def beforeInsert() {
    encodePassword()
}

def beforeUpdate() {
    if (isDirty('password')) {
        encodePassword()
    }
}

protected void encodePassword() {
    password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}

static transients = ['springSecurityService']

static constraints = {
    username blank: false, unique: true
    password blank: false, minSize: 5, validator: { pass, user ->
        pass != user.username
    }
    uniqueId blank: false, unique: true, range: 1000..2000000000

    profile unique: true, nullable: true
    contents nullable: true
}

static mapping = {
    password column: '`password`'
    profile fetch: 'join'
}

}

配置文件域类:

package com.clinton.kiitsocial

class Profile {
    String bio
    String contact
    String address
    GenderList gender
    String emailId
    Avatar avatarImage
    User user

    static hasMany = [socialNetworks: Social]

    static constraints = {
        bio nullable: true, maxSize: 50
        address nullable: true, maxSize: 50
        contact nullable: true, matches: "^\\+(?:[0-9] ?){6,14}[0-9]\$"
        socialNetworks nullable: true, unique: true
        gender nullable: true, blank: false
        emailId email: true, blank: true
        avatarImage nullable: true
    }
}

用户控制器:

@Secured(['ROLE_ADMIN', 'ROLE_USER'])
class UserController extends RestfulController {
    static responseFormats = ['json', 'xml']
    def userService
    UserController() {
        super(User)
    }

    def uploadAvatar() {
        MultipartFile avatar = request.getFile('avatar')
        avatar ? respond (userService.uploadingAvatar(avatar)): respond (500)
    }

    def showAvatar() {
    }
}

用户服务:

package com.clinton.kiitsocial

import grails.plugin.springsecurity.SpringSecurityService
import grails.transaction.Transactional
import org.springframework.web.multipart.MultipartFile

@Transactional
class UserService {

    SpringSecurityService springSecurityService
    private static final acceptedAvatarTypes = ['image/png', 'image/jpeg', 'image/gif']

    User uploadingAvatar(MultipartFile file) {
        User user = (User) springSecurityService.currentUser
        Profile profile = Profile.findOrSaveByUser(user)
        assert profile.user.username == user.username
        //assert !profile.avatarImage
        String message = ""
        if (!acceptedAvatarTypes.contains(file.contentType)) {
            //message = "Avatar must be one of: ${acceptedAvatarTypes} type"
            //respond 500
            return user
        }
        profile.avatarImage = new Avatar(avatar: file.bytes, avatarType: file.contentType)
        println("uploading: ${profile.avatarImage.avatarType}")
        if (!profile.save(failOnError: true, flush: true)) { //Error ocurs here
            message = "error occurred saving image"
            println("${profile.errors}")
            //respond user.errors
            return user
        }
         message = "Avatar (${profile.avatarImage.avatarType}, ${profile.avatarImage.avatar.size()} bytes) uploaded."
         println(message)
        println("finishing...")
        return user
    }

    /*def showAvatar(long  userId) {
        def avatarUser = User.get(userId)
        if (!avatarUser || !avatarUser.profile.avatarImage || !avatarUser.profile.avatarType) {
            //respond 404
            return
        }
        response.contentType = avatarUser.profile.avatarType
        response.contentLength = avatarUser.profile.avatarImage.size()
        OutputStream out = response.outputStream
        out.write(avatarUser.profile.avatarImage)
        out.close()
    }*/
}

错误/堆栈跟踪:

我花了两天时间试图解决这个问题。欢迎所有建议。谢谢你抽出时间。。

共有1个答案

辛承志
2023-03-14

我想出来了。我对它进行了集成测试,并得出结论:hibernate需要在将内部域附加到父域之前对其进行持久化和刷新。喜欢自下而上的时尚。见下面的答案。这是由瞬态域实例引起的。

Avatar uploadingAvatar(MultipartFile file) {
        User user = (User) springSecurityService.currentUser
        if (!user.profile) user.profile = new Profile(user: user).save(flush: true)
        if (!acceptedAvatarTypes.contains(file.contentType)) {
            responseCode = 500
        }

        Avatar avatar = user.profile.avatarImage ?: new Avatar()
        avatar.avatarName = file.originalFilename
        avatar.avatarBytes = file.bytes
        avatar.avatarType = file.contentType
        if (!avatar.validate() && !avatar.save(flush: true)){
            responseCode = 500
            return avatar
        }
        user.profile.avatarImage = avatar
        println("Avatar changed success")
        responseCode = 200
        return avatar
    }
 类似资料:
  • 我正在尝试使用Laravel保存方法保存关系: var_转储请求- 我已经在模型上尝试过填充和保护,但没有任何效果。但是,save方法不需要这些,因为它使用了一个完整的雄辩的模型实例。 我在这里错过了什么??

  • 我在实体“任务”和实体“用户”之间有双向关联。 “任务”定义如下 “用户”的定义是 从两个方向访问关系很好。问题是,一旦定义了“Task”实体,我就无法更新它。 这是一个测试案例 我做错了什么?

  • 问题内容: 我正在NHibernate中对单个属性执行标准更新。但是,在提交事务时,sql更新似乎设置了我映射到表上的所有字段,即使它们没有更改。当然这不是Nhibernate中的正常行为吗?难道我做错了什么?谢谢 问题答案: 这是正常现象。您可以尝试添加到类定义中以覆盖此行为。

  • 问题内容: 我设计数据存储的背景来自iOS上的Core Data,它支持与另一个实体具有一对多关系的属性。 我正在开发一个App Engine项目,该项目目前具有三种实体类型: ,代表使用该应用程序的人。 ,代表一个项目。A可能与许多项目相关联。 ,这是背后的主要内容。A可能有很多职位。 当前,它具有属性,即与实体的一对多关系。具有一个属性,即与实体一对多的关系。 在这种情况下,数据存储的参考属性

  • 本文向大家介绍写一个方法遍历指定对象的所有属性相关面试题,主要包含被问及写一个方法遍历指定对象的所有属性时的应答技巧和注意事项,需要的朋友参考一下

  • 下面包含我的controller类中的代码,我使用方法public String getRegistrationForm(Map model)返回一个带有spring表单的jsp-page,在这个方法中,我设置了UserTab.SetisMfAEnabled(new Boolean(true)),在提交表单时调用方法:public String registerUser(@modelAttribu