【问题标题】:manytomany relation not able to save mapped id in mapping table in play frameworkmanytomany 关系无法在播放框架的映射表中保存映射的 id
【发布时间】:2014-11-15 11:08:55
【问题描述】:

我正在使用 play2.2.1 并尝试在 JobadsJobCategory 模型之间创建多对多关系。

我的Jobads.java

package models;

@Entity
public class Jobads extends Model {

    @Id
    public Long id;

    @ManyToOne
    public Employers employer;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "jobads_jobcategories")
    public List<Jobcategories> jobcategory;

    @ManyToOne
    public Joblocations joblocations;

    @Required
    public String jobtype;

    @Required
    public String title;

    @Required
    public String text;

    @Required
    public Long salary;

    @Required
    public String experience;

    @Required
    public String active;

    @Formats.DateTime(pattern="yyyy-MM-dd hh:mm:yy")
    public Date created_time = new Date();

    @Formats.DateTime(pattern="yyyy-MM-dd hh:mm:yy")
    public Date modified_time ;

    @Required
    @Formats.DateTime(pattern="yyyy-MM-dd")
    public Date expire_date ;

    public static Finder<Long,Jobads> find = new Finder<Long,Jobads>(
            Long.class, Jobads.class
    );

    public static Jobads create(Jobads ja) {
        ja.save();  
        ja.saveManyToManyAssociations("jobcategory");    
        return ja; 
    }
}

我的看法:

<form action="@routes.JobAdController.save()" method="post" onsubmit="return checkEmpty();">
    <div class="row">
        <div class="col-md-6">
            <div class="block">
                <div class="header">
                    <h2>Create A New Job</h2>
                </div>
                <div class="content controls">
                    <div class="form-row">
                        <div class="col-md-3">Employer</div>
                        <div class="col-md-9">
                            <select class="form-control" name="employer.id" id="employer_id">
                                <option value="select">Select Employer</option>
                                @for(emp<-employersList) {
                                    <option value="@emp.id">@emp.company_name</option>
                                }
                            </select>
                        </div>
                    </div>
                    <div class="form-row">
                        <div class="col-md-3">Category</div>
                        <div class="col-md-9">
                            <select class="form-control" name="jobcategory.id" id="jobcategory_id">
                                <option value="select">Select Job Category</option>
                                @for(jc<-jobcategoryList) {
                                    <option value="@jc.id">@jc.name</option>
                                }
                            </select>
                        </div>
                    </div>   
                    <div class="form-row">
                        <div class="col-md-3">Location</div>
                        <div class="col-md-9">
                            <select class="form-control" name="joblocations.id" id="joblocation_id">
                                <option value="select">Select Job Location</option>
                                @for(jl<-joblocationList) {
                                    <option value="@jl.id">@jl.country,@jl.state,@jl.city</option>
                                }
                            </select>
                        </div>
                    </div>
                    <div class="form-row">
                        <div class="col-md-3">Job Type</div>
                        <div class="col-md-9">
                            <select class="form-control" name="jobtype" id="jobtype">
                                <option value="select">Select Job Type</option>
                                <option value="parttime">Part Time</option>
                                <option value="fulltime">Full Time</option>
                            </select>
                        </div>
                    </div>
                    <div class="form-row">
                        <div class="col-md-3">Title</div>
                        <div class="col-md-9"><input type="text" class="form-control" placeholder="Title" name="title" required="required"/></div>
                    </div>
                    <div class="form-row">
                        <div class="col-md-3">Text</div>
                        <div class="col-md-9"><textarea class="form-control" name="text" required="required"></textarea></div>
                    </div>
                    <div class="form-row">
                        <div class="col-md-3">salary</div>
                        <div class="col-md-9"><input type="text" class="form-control" placeholder="Salary per month"  name="salary" required="required"/></div>
                    </div>
                    <div class="form-row">
                        <div class="col-md-3">expire date</div>
                        <div class="col-md-9"><input type="date"   class="form-control" placeholder="expiry date" name="expire_date" id="expire_date"  required="required" /></div>
                        <input type="hidden"   class="form-control" placeholder="expiry date" name="exp_date" id="exp_date" />
                    </div>
                    <div class="form-row">
                        <div class="col-md-3">Active</div>
                        <div class="col-md-9">
                            <select class="form-control" name="active" id="active">
                                <option value="active">Active</option>
                                <option value="inactive">Inactive</option>
                            </select>
                        </div>
                    </div>
                    <div class="form-row">
                        <div class="col-md-12">
                            <button type="submit" class="btn btn-default btn-block">Add</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

还有我的控制器:

public class JobAdController extends Controller {
    public static Result save() {

        Form<Jobads> jobadsFormData = jobadsForm.bindFromRequest();
        if (jobadsFormData.hasErrors()) {
            System.out.println("Error in form");
            return badRequest();
        } else {
            Jobads.create(jobadsFormData.get());
            return redirect(controllers.routes.JobAdController.index());
        }
    }
}

我在 Jobcategory 模型中没有 Jobads 的变量,因为我不需要它。因此会创建一个名为 jobads_jobcategories 的默认表。我的问题是,当我尝试在 jobads 表中插入数据时,它已完美插入,但映射 ID 未保存在 jobads_jobcategories 表中。

【问题讨论】:

  • 您是否尝试过将字段访问权限更改为“私有”并添加 getter 和 setter?
  • @rtruszk 按照您的建议尝试了,但仍然是同样的问题
  • 我试图重现您的问题,但它对我有用。请在您的帖子中添加更多代码。在您创建工作和类别的位置添加代码。
  • @rtruszk 更新了我的问题,你能发布你的代码吗?它会很有帮助

标签: playframework many-to-many ebean


【解决方案1】:

感谢 rtruszk 的帮助,我的工作类别列表为空。 Play 无法将请求中的多值变量绑定到模型多对多列表变量(我仍在试图弄清楚 play 这样做的原因)

所以我做了什么来解决这个问题,我更改了表单方法以从控制器中的 url 获取多值变量的值,然后创建一个新列表并添加到我的表单变量中。这是可选的,但我添加了 getter 和 setter 并更改了我的列表名称。下面给出的代码

对于GET请求

public static Result save() {

    List<Long> jobCatList = new ArrayList<Long>();
    final Set<Map.Entry<String, String[]>> entries = request().queryString().entrySet();
    for (Map.Entry<String, String[]> entry : entries) {
        final String key = entry.getKey();
        final String value = Arrays.toString(entry.getValue());
        System.out.println(key + " " + value);
        if (key.equalsIgnoreCase("jobcategories.id")) {
            String val = value;
            val = val.replace("[", "");
            val = val.replace("]", "");
            String[] a = val.split(",");
            for (int i = 0; i < a.length; i++) {
                jobCatList.add(Long.parseLong(a[i].trim()));
            }
        }
    }
    List<Jobcategories> jobCatObList = new ArrayList<Jobcategories>();
    for (Long id : jobCatList) {
        System.out.println("Id are:" + id);
        jobCatObList.add(Jobcategories.findById(id));
    }
    System.out.println(request().getQueryString("jobcategories.id"));
    Form<Jobads> jobadsFormData = jobadsForm.bindFromRequest();
    System.out.println("\nCategory Form are:" + (jobadsFormData.get()).getJobcategories());
   (jobadsFormData.get()).setJobcategories(jobCatObList);
    if (jobadsFormData.hasErrors()) {
        return badRequest();
    } else {
        Jobads.create(jobadsFormData.get());
        return redirect(controllers.routes.JobAdController.index());
    }
}

对于POST请求

public static Result save() {

        Form<Jobads> jobadsFormData = jobadForm.bindFromRequest();

        Map<String, String[]> formUrlEncoded = request().body().asFormUrlEncoded();

        List<Jobcategories> fa = new ArrayList<Jobcategories>();


        for (String key : formUrlEncoded.keySet()) {
            String[] values = formUrlEncoded.get(key);
            for (String val : values) {
                if ("jobcategories.id".equals(key)) fa.add(Jobcategories.findById(Long.valueOf(val)));

            }
        }

            if (jobadsFormData.hasErrors()) {
            return badRequest();
        } else {
            (jobadsFormData.get()).setJobcategories(fa);

            Jobads.create(jobadsFormData.get());
            return redirect();

        }
    }

我知道这种方法不是保存多对多关系的正确方法,但我没有其他选择来解决我的问题。

如果有人有更好的解决方案,请发布它,因为我已经尝试了几天并且已经取得了很多成就。

为什么 play 不能映射或保存多对多关系?

【讨论】:

    【解决方案2】:

    您的映射很好。尝试运行以下测试以确保这一点:

    @Test
    public void ebeanTest() {
        FakeApplication app = Helpers.fakeApplication(Helpers.inMemoryDatabase());
        Helpers.start(app);
    
        Jobcategories jc = new Jobcategories();
        jc.id=1l;
        jc.title="cat 1";
    
        Jobads job = new Jobads();
        job.id=2l;
        job.title = "job 1";
        job.jobcategory.add(jc);
        Jobads.create(job);
    
        Jobads foundJob = Jobads.find.byId(2l);
    
        for(Jobcategories jobc:foundJob.jobcategory) {
            System.out.println("id: "+jobc.id);
            System.out.println("title: "+jobc.title);
        }       
    }
    

    你应该有以下结果:

    [play-java] $ test
    id: 1
    title: cat 1
    

    您还可以从 Jobads 类中删除以下行,因为它在那里已过时:

    ja.saveManyToManyAssociations("jobcategory");
    

    您的表单似乎有错误。我认为

    jobadsFormData.get()
    

    返回作业类别列表为空的 Jobads。然后这样的对象就被正确保存了。

    编辑 我在您的视图代码中看到您使用“选择”HTML 元素来选择 Jobcategories。你为什么这样做?您的 Jobads 类中有 Jobcategories 列表,但在“select”元素中,您只能选择一个类别。因此,此 HTML 元素适用于选择雇主或工作地点,但不适用于选择列表。所以这就是问题所在。 'select' 元素映射到字段,但不映射到列表。

    EDIT2 所以你必须改变两件事:

    1. 将 multiple="multiple" 添加到您的 HTML 选择元素中
    2. 在保存表单时检查选择了哪些类别。详情请见this post

    【讨论】:

    • 抱歉回复晚了,你说得对,我的观点是发送一个空的工作类别列表,但问题仍然相同,为什么 play 无法将请求数据绑定到我相应的多线程列表试图解决这个问题无论如何感谢您为我指明正确的方向
    • @singhakash 所以也许可以在您的问题中添加更多代码。也许你的表格代码。我可以尝试改进我的答案。
    • 我很抱歉在我的代码中做了很多更新,因为我已经将它发布在堆栈上忘记在上面的选择标签中添加多个,但这不应该是它应该为列表发送一个元素的原因
    【解决方案3】:

    尝试为jobads和/或jobcategories添加JoinColumn

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "jobads_jobcategories", joinColumns = {@JoinColumn(name="Jobads_ID", referencedColumnName="ID")})
    public List<Jobcategories> jobcategory;
    

    我想在评论中询问您是否尝试,但我没有足够的声誉。

    【讨论】:

    • 我试过了,但遇到了同样的问题
    猜你喜欢
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-17
    • 2019-03-27
    • 1970-01-01
    • 2013-01-17
    • 2016-02-21
    相关资源
    最近更新 更多