gpt4 book ai didi

java - Spring MVC + hibernate : a form with checkboxes for @manytomany relationship

转载 作者:行者123 更新时间:2023-11-30 03:50:07 24 4
gpt4 key购买 nike

这周我一直在尝试在网络开发中做一件非常简单的事情:一个带有复选框的表单,我可以在其中勾选哪些机构参与了竞赛。

代理机构 --> ContestAgency <-- 竞赛

比赛类别:

// i tried also EAGER
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.contest", cascade=CascadeType.ALL)
private Set<ContestAgency> contestAgencies = new TreeSet<ContestAgency>();

代理类别:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.agency", cascade=CascadeType.ALL)
private Set<ContestAgency> contestAgencies = new TreeSet<ContestAgency>();

如何在 WebFlow 或 Controller 中制作带有复选框的表单?

谢谢

最佳答案

我找到了解决方案。我不认为这是最好的,但它有效:

  • 在 View 中,我为所有复选框指定了名称(chk_services、chk_agcies)

  • 在过渡到下一步时,我采用 POST 生成的逗号分隔字符串以及已检查的 ID(id1、id2、...),然后传递给方法它分割字符串,对于每个 id,从数据库中获取相关实体并将它们放入我的多对多实体集(ContestService)中

< evaluate expression="contestFlow.converterCheckboxToSetContestService(flowScope.contest, requestParameters.chk_services)" result="flowScope.contest.ContestServices"> < /evaluate >

(当我进入下一步和上一步时我都会这样做)

  • 进入 View 时,我想再次检查复选框。为此,我需要将我的 Set 转换为 ids 列表:
  < set name="viewScope.checked_services" value="contestFlow.converterSetContestServiceToCheckbox(flowScope.contest.ContestServices)" / >
  • 在 View 中,我查看是否选中每个复选框:

    th:checked="${#lists.contains(checked_services, '' + service_el.id)}"

注意:需要 '' + service_el.id,没有 '' + 则不起作用



我发布完整代码。我希望有人会觉得它有用。

欢迎任何改进和建议。

Web应用程序配置(我正在使用java注释):使用流程中使用的方法配置 bean

public class WebAppConfig extends WebMvcConfigurerAdapter {

//...

@Bean
public ContestFlow contestFlow()
{
return new ContestFlow();
}

}

使用我的方法的 ContestFlow bean:

@Component
public class ContestFlow {

static Logger logger = LoggerFactory.getLogger(ContestFlow.class);

@Autowired
private ServiceService ServiceService;

@Autowired
private AgencyService AgencyService;

/**
* input: a comma separated string with all ids checked from the POST
*
* @param contest: contest object that i will add at the end of the webflow
* @param ids_string: comma separated string with checked ids
* @return
*/
public Set<ContestService> converterCheckboxToSetContestService(Contest contest, String ids_string)
{

Set<ContestService> contestServices = new HashSet<ContestService>(0);

if (ids_string != null)
{
String[] arr_ids = ids_string.split(",");

/*
* for each record i get the Service
*/
for (int i = 0; i < arr_ids.length; i++)
{
try
{
//get the Service
Service service = ServiceService.getService(Integer.parseInt(arr_ids[i]));

logger.info("Aggiungo il service id [" + arr_ids[i] + "]");

//creation of the Id object
ContestServiceId contestServiceId = new ContestServiceId();
contestServiceId.setService(service);
contestServiceId.setContest(contest);

//record population
ContestService contestService = new ContestService();
contestService.setService(service);
contestService.setContest(contest);
contestService.setPk(contestServiceId);

//add the record
contestServices.add(contestService);

}
catch(Exception ex)
{
ex.printStackTrace();
logger.info("Service id [" + arr_ids[i] + "] not found!");

}

}
}
return contestServices;
}


/**
* input: Set of ContestAgency (many-to-many) checked
* and returns a List<String> of ids to be used to select checkboxes
* in thymeleaf view with th:checked="${#lists.contains(checked_agencies, '' + agency_el.id)}"
*
* i can't return a List<Integer> because it doesn't check the checkboxes
*
* @param contestAgencies
* @return
*/
public List<String> converterSetContestServiceToCheckbox(Set<ContestService> contestServices)
{
List<String> result = new ArrayList<String>();

if (contestServices != null)
{
Iterator<ContestService> iterator = contestServices.iterator();
while(iterator.hasNext())
{
ContestService contestService = iterator.next();

Integer id = contestService.getService().getId();

result.add(id.toString());
}
}

return result;
}




//same as above, for the Agencies:





/**
* input: a comma separated string with all ids checked from the POST
*
* @param contest: contest object that i will add at the end of the webflow
* @param ids_string: comma separated string with checked ids
* @return
*/
public Set<ContestAgency> converterCheckboxToSetContestAgency(Contest contest, String ids_string)
{

Set<ContestAgency> contestAgencies = new HashSet<ContestAgency>(0);

if (ids_string != null)
{
String[] arr_ids = ids_string.split(",");

/*
* for each record i get the Agency
*/
for (int i = 0; i < arr_ids.length; i++)
{
try
{
//get the Agency
Agency agency = AgencyService.getAgency(Integer.parseInt(arr_ids[i]));

logger.info("Adding agency id [" + arr_ids[i] + "]");

//creation of the Id object
ContestAgencyId contestAgencyId = new ContestAgencyId();
contestAgencyId.setAgency(agency);
contestAgencyId.setContest(contest);

//record population
ContestAgency contestAgency = new ContestAgency();
contestAgency.setAgency(agency);
contestAgency.setContest(contest);
contestAgency.setPk(contestAgencyId);
contestAgency.setContractCount(0); //my many-to-many relationship has an additional field

//add the record
contestAgencies.add(contestAgency);

}
catch(RecordNotFoundException ex)
{
ex.printStackTrace();
logger.info("Agency id [" + arr_ids[i] + "] not found!");

}

}
}
return contestAgencies;
}


/**
* input: Set of ContestAgency (many-to-many) checked
* and returns a List<String> of ids to be used to select checkboxes
* in thymeleaf view with th:checked="${#lists.contains(checked_agencies, '' + agency_el.id)}"
*
* i can't return a List<Integer> because it doesn't check the checkboxes
*
* @param contestAgencies
* @return
*/
public List<String> converterSetContestAgencyToCheckbox(Set<ContestAgency> contestAgencies)
{
List<String> result = new ArrayList<String>();

if (contestAgencies != null)
{
Iterator<ContestAgency> iterator = contestAgencies.iterator();
while(iterator.hasNext())
{
ContestAgency contestAgency = iterator.next();

Integer id = contestAgency.getAgency().getId();

result.add(id.toString());
}
}

return result;
}

}

第 2 步 View :带有服务复选框的表单:

<ul class="list-unstyled">
<!--
- parent and children are saved in the same table, so i'm not worried about ids overlapping
-->

<li th:each="service_el : ${services_list}" >
<input type="checkbox" name="chk_services" th:value="${service_el.id}" th:checked="${#lists.contains(checked_services, '' + service_el.id)}"/>
<label th:text="${service_el.title}" th:for="'chk_services' + ${service_el.id}">service</label>

<ul class="list-unstyled-padding">
<li th:each="subservice_el : ${service_el.children}">
<input type="checkbox" name="chk_services" th:value="${subservice.id}" th:checked="${#lists.contains(checked_services, '' + subservice.id)}"/>
<label th:text="${subservice.title}" th:for="'chk_services' + ${service_el.id}">subservice</label>
</li>
</ul>
</li>
</ul>

第 3 步 View :带有代理机构复选框的表单:

<ul class="list-unstyled">
<li th:each="agency_el : ${agencies_list}">
<input name="chk_agencies" type="checkbox" th:id="'chk_agencies' + ${agency_el.id}" th:value="${agency_el.id}" th:checked="${#lists.contains(checked_agencies, '' + agency_el.id)}" />
<label th:text="${agency_el.name}" th:for="'chk_agencies' + ${agency_el.id}">agency</label>
</li>
</ul>

最后:流程xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

<secured attributes="ROLE_USER" />

<!-- creation of an empty object i will insert in db in the last step -->
<on-start>
<evaluate expression="ContestService.createContest()" result="flowScope.contest" />
</on-start>

<!--
step 1: contest details
-->
<view-state id="contest-details" model="contest">
<binder>
<binding property="startDate" required="true" />
<binding property="endDate" required="true"/>
<binding property="bonus" required="true"/>
<binding property="goal" required="true"/>
<binding property="title" required="true"/>
</binder>
<transition on="proceed" to="contest-services">
</transition>
<transition on="cancel" to="cancel" bind="false" />
</view-state>

<!--
step 2: i select which services are involved
-->
<view-state id="contest-services" model="contest">
<on-entry>
<!--
- in case i'm coming here from the step 3
- injection of the list of ids previously checked
-->
<set name="viewScope.checked_services" value="contestFlow.converterSetContestServiceToCheckbox(flowScope.contest.ContestServices)" />

<!--
- i get the list of the Main Services
- subservices will be scanned with getChildren method
-->
<set name="viewScope.services_list" value="ServiceService.getMainServices()" />
</on-entry>

<transition on="proceed" to="contest-agencies" >
<!--
- MY SOLUTION TO MANY-TO-MANY checkboxes form:
-
- honestly not very elegant, but in 10 day i could't find better
-
- conversion from String to Set<ContestService>
-->
<evaluate expression="contestFlow.converterCheckboxToSetContestService(flowScope.contest, requestParameters.chk_services)" result="flowScope.contest.ContestServices"></evaluate>
</transition>

<transition on="cancel" to="contest-details">
<!--
- also if i go back in the flow, to the first step,
- i need to remember which checkboxes were selected
-
- and i need to save the checked services to the Contest entity,
- else, when i will call addContest method,
- it will not save the checked Services
-->
<evaluate expression="contestFlow.converterCheckboxToSetContestService(flowScope.contest, requestParameters.chk_services)" result="flowScope.contest.ContestServices"></evaluate>
</transition>
</view-state>




<!--
step 3: i select which agencies are involved in contest.
only agencies enabled for previously checked services are shown
-->
<view-state id="contest-agencies" model="agencies">
<on-entry>
<!--
- in case i'm coming here from the step 3
- injection of the list of ids previously checked
-->
<set name="viewScope.checked_agencies" value="contestFlow.converterSetContestAgencyToCheckbox(flowScope.contest.ContestAgencies)" />

<!--
- only agencies enabled for the step 2 checked services are shown
-->
<set name="viewScope.agencies_list" value="AgencyService.getEnabledAgenciesForServices(contestFlow.converterSetContestServiceToCheckbox(flowScope.contest.ContestServices))" />
</on-entry>

<transition on="proceed" to="contest-confirm" >
<!--
- MY SOLUTION TO MANY-TO-MANY checkboxes form:
-
- honestly not very elegant, but in 10 day i could't find better
-
- conversion from String to Set<ContestAgency>
-->
<evaluate expression="contestFlow.converterCheckboxToSetContestAgency(flowScope.contest, requestParameters.chk_agencies)" result="flowScope.contest.ContestAgencies"></evaluate>
</transition>

<transition on="cancel" to="contest-services">
<!--
- MY SOLUTION TO MANY-TO-MANY checkboxes form:
-
- honestly not very elegant, but in 10 day i could't find better
-
- conversion from String to Set<ContestAgency>
-
- and i need to save the checked Agencies to the Contest entity,
- else, when i will call addContest method,
- it will not save the checked Agencies
-->
<evaluate expression="contestFlow.converterCheckboxToSetContestAgency(flowScope.contest, requestParameters.chk_agencies)" result="flowScope.contest.ContestAgencies"></evaluate>
</transition>
</view-state>


<!--
- data confirmation before insert in db
-->
<view-state id="contest-confirm" model="contest">
<transition on="proceed" to="contest-end" >
<evaluate expression="ContestService.addContest(contest)" />
</transition>
<transition on="cancel" to="contest-agencies" />
</view-state>



<!--
end: redirect to list
-->
<end-state id="contest-end" view="externalRedirect:contextRelative:/contest/list"/>

<!--
cancella
-->
<end-state id="cancel"/>

</flow>

关于java - Spring MVC + hibernate : a form with checkboxes for @manytomany relationship,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24673798/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com