2012-10-22 23 views
5

Tôi hiện đang phát triển một ứng dụng Grails và tôi đang làm việc với các trình cắm thêm Spring Security và UI. Tôi đã tạo ra mối quan hệ giữa các lớp người dùng và Lớp Diện tích khác mà tôi có mà có thể được nhìn thấy dưới đây:Grails - lưu các trường hợp thoáng qua trước khi xả grails Lỗi?

tài Class:

class User { 

    transient springSecurityService 

    String username 
    String email 
    String password 
    boolean enabled 
    boolean accountExpired 
    boolean accountLocked 
    boolean passwordExpired 

    static belongsTo = [area:Areas] 

     ....... 
} 

Diện tích Class:

class Areas { 

    String name 

    static hasMany = [users:User] 

} 

Như bạn có thể nhìn thấy từ các lớp, một người dùng có thể được liên kết với một khu vực nhưng một khu vực có thể có nhiều người dùng. Điều này tất cả các công trình tốt và khi tôi khởi động ứng dụng tất cả các dữ liệu được thêm vào một cách chính xác. Tuy nhiên tôi nhận được lỗi sau khi tôi cố gắng sử dụng một hình thức để tạo ra một người dùng mới:

object references an unsaved transient instance - save the transient instance before flushing: com.website.Area 

dưới đây là các mã điều khiển Tôi đang sử dụng để lưu thông tin:

def save = {  
     def user = lookupUserClass().newInstance(params) 

     if (params.password) { 
      String salt = saltSource instanceof NullSaltSource ? null : params.username 
      user.password = springSecurityUiService.encodePassword(params.password, salt) 
     } 

     if (!user.save(flush: true)) { 
      render view: 'create', model: [user: user, authorityList: sortedRoles()] 
      return 
     } 

     addRoles(user) 
     flash.message = "${message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), user.id])}" 
     redirect action: edit, id: user.id 
    } 

và đây là một mẫu của những gì GSP trông giống như:

<table> 
     <tbody> 

      <s2ui:textFieldRow name='username' labelCode='user.username.label' bean="${user}" 
          labelCodeDefault='Username' value="${user?.username}"/> 

      <s2ui:passwordFieldRow name='password' labelCode='user.password.label' bean="${user}" 
           labelCodeDefault='Password' value="${user?.password}"/> 

      <s2ui:textFieldRow name='email' labelCode='user.email.label' bean="${user}" 
           labelCodeDefault='E-Mail' value="${user?.email}"/> 

      <s2ui:textFieldRow readonly='yes' name='area.name' labelCode='user.area.label' bean="${user}" 
           labelCodeDefault='Department' value="${area.name}"/> 


      <s2ui:checkboxRow name='enabled' labelCode='user.enabled.label' bean="${user}" 
          labelCodeDefault='Enabled' value="${user?.enabled}"/> 

      <s2ui:checkboxRow name='accountExpired' labelCode='user.accountExpired.label' bean="${user}" 
          labelCodeDefault='Account Expired' value="${user?.accountExpired}"/> 

      <s2ui:checkboxRow name='accountLocked' labelCode='user.accountLocked.label' bean="${user}" 
          labelCodeDefault='Account Locked' value="${user?.accountLocked}"/> 

      <s2ui:checkboxRow name='passwordExpired' labelCode='user.passwordExpired.label' bean="${user}" 
          labelCodeDefault='Password Expired' value="${user?.passwordExpired}"/> 
     </tbody> 
     </table> 

tôi đã nhìn vào trong này và tôi tin rằng nó là cách tôi đang cố gắng để tiết kiệm một Object GORM và tôi có lẽ nên lưu phụ huynh (Area) trước khi cố gắng để lưu các người dùng. Tuy nhiên, Khu vực sẽ luôn tồn tại trước khi người dùng có thể được tạo nên tôi không cần khu vực được tạo lại, làm cách nào để xử lý vấn đề này? Tôi đã thử chức năng "withTransaction" với ít thành công cũng như

Tôi thực sự đánh giá cao một số trợ giúp về điều này nếu có thể.

Cảm ơn

EDIT ......

Tôi đã theo dõi vấn đề này đến đường dây này trong Bộ điều khiển:

RegistrationCode registrationCode = springSecurityUiService.register(user, command.password, salt) 

này nói với tôi rằng chức năng này được gọi một lưu chức năng cho đối tượng người dùng, tuy nhiên với các mối quan hệ tại chỗ nó cần phải lưu Khu vực đầu tiên. Có ai biết SpringSecurityUi để giúp tôi về điều này?

Cảm ơn

+0

Đặt dịch vụ lò xo trong bộ điều khiển chứ không phải lớp miền. – marko

+0

Bạn có thể cho tôi một ví dụ không? vì springecurityservice luôn ở đó – user723858

+0

Lỗi có không liên quan đến lớp "com.website.Area" như lỗi nói không? Cảm ơn – user723858

Trả lời

7

Các thông báo lỗi mà bạn nhìn thấy

object references an unsaved transient instance - save the transient instance before flushing: com.website.Area 

... xảy ra khi bạn đang cố gắng lưu một phụ huynh không tồn tại (tức là Khu vực) vi tity từ một thực thể con (tức là người dùng). Có thể lỗi xảy ra trong phương thức RegistrationController.register như bạn đã chỉ ra, nếu đó là nơi bạn đang lưu Người dùng mới.

RegistrationCode registrationCode = springSecurityUiService.register(user, command.password, salt) 

Bạn chỉ cần cập nhật mã đăng ký .đăng ký phương thức với logic để gán Diện tích cho Người dùng (giả sử Khu vực đã tồn tại) trước khi cuộc gọi đăng ký - dưới đây là một ví dụ nhanh.

class RegistrationController .. 
.. 
def area = Area.findByName(command.areaName) 
def user = lookupUserClass().newInstance(email: command.email, username: command.username, 
       accountLocked: true, enabled: true, area: area) 
RegistrationCode registrationCode = springSecurityUiService.register(user, command.password, salt) 

Một vài lưu ý:

  • bạn đang đi qua lại "area.name" khỏi tầm nhìn GSP của bạn, vì vậy bạn sẽ cần phải cập nhật/ghi đè RegisterCommand để bao gồm các Diện tích tên
  • là việc bạn sử dụng Khu vực "tên" làm số nhận dạng an toàn không? Trong định nghĩa lớp học của bạn, bạn không có ràng buộc để chỉ ra rằng "tên" sẽ là duy nhất. Có lẽ qua lại một Diện tích id khỏi tầm nhìn của bạn là an toàn hơn
  • lý tưởng bạn nên xử lý các Diện tích tra cứu với một trình soạn thảo bất động sản tùy chỉnh - đây là một ví dụ: Grails command object data binding

Anyways, hy vọng rằng sẽ giúp.

+0

Trình tiết kiệm cuộc sống :-) Tôi đã khắc phục sự cố trong một phần của giải pháp tuy nhiên điều này thực sự đã giúp tôi giải quyết một câu hỏi khác :-D – user723858

+0

Câu trả lời hay nhất ... và giải thích tốt cho câu hỏi –

1

Cố gắng biến phụ thuộc hai chiều sang phía bên kia

class Areas { 

    String name 
    static belongsTo = [User] 
    static hasMany = [users:User] 
} 

Đừng quên để loại bỏ belongsTo từ tài

1
class Areas { 
    String name 
    static belongsTo = [User] 
    static hasMany = [users:User] 
} 
Các vấn đề liên quan