我不是Hibernate的专家,所以这个问题打破了我的大脑。
我前段时间用
编写了一个Web应用程序此应用程序的主要用途 - 使用瘦Web客户端编辑一个组织中的客户端数据数据库。
工作流程如下所述:
在用户工作日期间有一个客户端队列。
<p:dataTable>
,其中每一行都是找到的客户列表的对象。rowKey="#{client.id}" selectionMode="single" selection="#{clientform.client}"
),用户使用“客户端”类型设置ManagedBean(ClientForm)的属性:ClientFormBean.java:
@ManagedBean(name = "clientform")
@SessionScoped
public class ClientFormBean implements Serializable {
private Client client;
}
这里使用的是SessionScope,因为由于某些限制,用户此时只能编辑一个客户端。
当下一个客户端访问用户时,用户转到步骤1,然后找到下一个客户端等等。
它几乎总是正常工作,但是,随机地,一周1-2次(或两周内)以前客户端数据的大部分(仅客户端类型和客户端的一对多连接)被覆盖在对数据库的持久操作期间,实际客户端的数据(在ClientFormBean.client中)。
我使用下一个DAO方法:
@Repository
public class GenericDAO implements IGenericService, Serializable {
@Autowired
private SessionFactory sessionFactory;
public <T> void updateInstance(T instance) {
getSessionFactory().getCurrentSession().saveOrUpdate(instance);
}
}
如果有人能说出我为什么会这样,以及如何解决这个问题,我将不胜感激,因为实际上我无法理解如何找到识别问题的方法(可能是已知的问题?)。
当用户加载新客户端的数据时,可能需要在上次对象的任何时候禁用缓存或evict()(我不知道它是如何可能的,因为用户使用<p:dataTable>
选择新客户端PrimeFaces选择器)。
Hibernate属性:
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
</props>
</property>
<tx:annotation-driven transaction-manager="txManager" />
<tx:annotation-driven proxy-target-class="true"/>
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
提前致谢!
增加:
客户端 - 是主要实体,Hibernate只合并这个实体及其关系(它们是POJO classess所以我没有将它们附加到问题上)。
@Entity
@Table(name = "Client")
public class Client implements Serializable {
private int id;
private String surname;
private String middlename;
private String firstname;
private Set<ChronicDisease> diseases;
private NightStay nightStay;
private Education education;
private Set<Breadwinner> breadwinners;
private Set<Reasonofhomeless> reasonofhomeless;
private FamilyCommunication fcom;
private Set<RecievedService> recievedservices;
@ManyToMany(cascade = CascadeType.ALL ,targetEntity = ChronicDisease.class)
@JoinTable(name = "link_chronicdisease_client",
joinColumns = @JoinColumn(name = "clients_id", nullable = false, updatable = false),
inverseJoinColumns = @JoinColumn(name = "diseases_id", nullable = false, updatable = false)
)
public Set<ChronicDisease> getDiseases() {
return diseases;
}
@ManyToOne(targetEntity = NightStay.class)
@JoinColumn(name = "nightStay")
public NightStay getNightstay() {
return nightStay;
}
@ManyToOne(targetEntity = Education.class)
@JoinColumn(name = "education")
public Education getEducation() {
return education;
}
@ManyToMany(cascade = CascadeType.ALL ,targetEntity = Breadwinner.class)
@JoinTable(name = "link_breadwinner_client",
joinColumns = @JoinColumn(name = "clients_id", nullable = false, updatable = false),
inverseJoinColumns = @JoinColumn(name = "breadwinners_id", nullable = false, updatable = false)
)
public Set<Breadwinner> getBreadwinners() {
return breadwinners;
}
@ManyToMany(cascade = CascadeType.ALL ,targetEntity = Reasonofhomeless.class)
@JoinTable(name = "link_reasonofhomeless_client",
joinColumns = @JoinColumn(name = "clients_id", nullable = false, updatable = false),
inverseJoinColumns = @JoinColumn(name = "reasonofhomeless_id", nullable = false, updatable = false)
)
public Set<Reasonofhomeless> getReasonofhomeless() {
return reasonofhomeless;
}
@ManyToOne(targetEntity = FamilyCommunication.class)
@JoinColumn(name = "familycommunication")
public FamilyCommunication getFcom() {
return fcom;
}
@OneToMany(targetEntity = RecievedService.class, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "client")
public Set<RecievedService> getRecievedservices() {
return recievedservices;
}
@ManyToOne(targetEntity = SubRegion.class)
@JoinColumn(name = "lastLiving")
public SubRegion getLastLiving() {
return lastLiving;
}
@ManyToOne(targetEntity = SubRegion.class)
@JoinColumn(name = "lastRegistration")
public SubRegion getLastRegistration() {
return lastRegistration;
}
}
以下是ClientFormBean.java的方法,它保存更改(有时将以前的数据与当前数据合并到数据库中):
public void saveClientForm() {
FacesMessage msg;
if (client != null) {
HttpSession session = Util.getSession();
String username = session.getAttribute("username").toString();
if (homelessDateNotNull) {
updateHomelessDate(selectedMonth, getSelectedYear());
} else {
Calendar cal = Calendar.getInstance();
cal.set(1900,0,1,0,0,0);
Date nullDate = cal.getTime();
client.setHomelessdate(nullDate);
}
client.setSurname(checkNameDash(client.getSurname()));
client.setFirstname(checkNameDash(client.getFirstname()));
client.setMiddlename(checkNameDash(client.getMiddlename()));
Set<Breadwinner> sb = new HashSet<Breadwinner>();
for (Breadwinner b : getClientService().getInstances(Breadwinner.class)) {
for (String cb : clientBreadwinners) {
if (b.getCaption().equals(cb)) {
sb.add(b);
}
}
}
client.setBreadwinners(sb);
Set<Reasonofhomeless> sr = new HashSet<Reasonofhomeless>();
for (Reasonofhomeless b : getClientService().getInstances(Reasonofhomeless.class)) {
for (String cb : clientReasonsofhomeless) {
if (b.getCaption().equals(cb)) {
sr.add(b);
}
}
}
client.setReasonofhomeless(sr);
Set<ChronicDisease> chd = new HashSet<ChronicDisease>();
for (ChronicDisease b : getClientService().getInstances(ChronicDisease.class)) {
for (String cb : clientChronicDisease) {
if (b.getCaption().equals(cb)) {
chd.add(b);
}
}
}
client.setDiseases(chd);
try {
getClientService().updateInstance(client);
msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Сохранено", "");
reloadAll();
} catch (Exception e) {
msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Клиент не сохранен!", "");
}
if (msg != null) {
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
}