manytomany relation not able to save mapped id in mapping table in play framework

牧云@^-^@ 提交于 2019-12-07 13:10:22

问题


I am using play2.2.1 and trying to create a ManyToMany relation between Jobads and JobCategory models.

My 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; 
    }
}

My view:

<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>

And my controller:

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());
        }
    }
}

I don't have a variable for Jobads in Jobcategory model because I dont need it there. So a default table is created named jobads_jobcategories. My problem is that when I am trying to insert a data in jobads table it is inserted perfectly but the mapping ids are not saved in jobads_jobcategories table.


回答1:


My jobcategorylist was empty thanks to rtruszk for helping me out. Play is not able to bind the mutiple valued variable from request to models manytomany list variable (I am still tryng to figure this out why play is doing that)

So what I did to solve this problem, I changed the form method to get the value of mutiple valued variable from url in my controller then created a new list and added to my Form variable. It's optional but I added getter and setter and changed my list name. Code given below

For GET request

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());
    }
}

OR

For POST request

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();

        }
    }

I know that this method is not the correct way of saving manytomany relation but I didn't have any other option to resolve my problem.

If anybody have a better solution then do post it because I am trying this for days and have achieves this much.

And why play is not able to map or save the manytomany relation?




回答2:


Your mapping is good. Try running following test to be sure of that:

@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);
    }       
}

You should have following result:

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

You can also remove following line from your Jobads class because it is obsolete there:

ja.saveManyToManyAssociations("jobcategory");

It seems that you have error in your form. I think that

jobadsFormData.get()

returns Jobads with empty list of jobcategories. And then such object is saved correctly.

EDIT I see in your view code that you use 'select' HTML element for selecting Jobcategories. Why do you do that? You have list of Jobcategories in your Jobads class but in 'select' element you can select only one category. So this HTML element is good for selecting employer or joblocation but not for selecting list. So here is the problem. 'select' element maps good to fielld but not to list.

EDIT2 So you have to change two things:

  1. Add multiple="multiple" to your HTML select element
  2. Check which categories are selected while saving form. See this post for details



回答3:


Try to add JoinColumn(s) for jobads and/or jobcategories

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

I want to ask if you try it in a comment, but I don't have enough reputation.



来源:https://stackoverflow.com/questions/26945159/manytomany-relation-not-able-to-save-mapped-id-in-mapping-table-in-play-framewor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!