Hibernate 自动保存一个全新的实体(完整的调用堆栈)
我已经问过这个问题两次了,但我是 stackoverflow 的新手,似乎我不知道在这里格式化示例代码的规则。现在我决定给出完整的调用堆栈,我希望我能解释一下情况,因为一切都很奇怪,我找不到词语来描述它。首先,我将向您提供与该问题有关的类的来源。我的实际问题在页面的末尾。大段代码是为了以防万一,因为我不知道什么可以解释我的问题。 这是一个从我的 Flex 应用程序获取调用的服务外观。
public class ServiceFacade implements IAuthenticationService, IProfileService, ICampaignService {
@Autowired
private IAuthenticationService authenticationService;
@Autowired
private IProfileService profileService;
@Autowired
private ICampaignService campaignService;
public void login(User user) throws AuthenticationException{
authenticationService.login(user);
}
@Override
public void logout() throws AuthenticationException {
authenticationService.logout();
}
@Override
public void sendForgottenPassword(String email) {
authenticationService.sendForgottenPassword(email);
}
@Override
public Profile getProfile(Long userId) {
return profileService.getProfile(userId);
}
@Override
public Profile updateProfile(Profile profile) {
return profileService.updateProfile(profile);
}
@Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileService.getSocialConnectionsTypes(userId);
}
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
return profileService.findDuplicateEmails(profileId, emails);
}
@Override
public Campaign getCampaign(Long campaignId) {
return campaignService.getCampaign(campaignId);
}
@Override
public Campaign updateCampaign(Campaign campaign) {
return campaignService.updateCampaign(campaign);
}
@Override
public void removeCampaign(Long campaignId) {
campaignService.removeCampaign(campaignId);
}
@Override
public void setPools(Long campaignId, Collection<Pool> pools) {
campaignService.setPools(campaignId, pools);
}
@Override
public void addPool(Long campaignId, Pool pool) {
campaignService.addPool(campaignId, pool);
}
@Override
public void removePool(Long campaignId, Pool pool) {
campaignService.removePool(campaignId, pool);
}
@Override
public List<Campaign> getCampaigns() {
return campaignService.getCampaigns();
}
@Override
public void updatePool(Long campaignId, Pool pool) {
campaignService.updatePool(campaignId, pool);
}
}
对于我的问题来说重要的方法是 findDuplicateEmails 方法。
profileService 在以下类中实现:
public class ProfileService implements IProfileService {
@Autowired
private IProfileManager profileManager;
@Override
public Profile getProfile(Long userId) {
return profileManager.getProfile(userId);
}
@Override
public Profile updateProfile(Profile profile){
profileManager.updateProfile(profile);
return profile;
}
@Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileManager.getSocialConnectionsTypes(userId);
}
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
return profileManager.findDuplicateEmails(profileId, emails);
}
}
同样重要的方法是 findDuplicateEmails
profileManager 的实现在以下类中:
public class ProfileManager implements IProfileManager {
@Autowired
private IProfileDao profileDao;
@Autowired
private ISectionManager autoCompleteManager;
@Autowired
private IUserSecurityService userSecurityService;
@Transactional
public Profile getProfile(Long userId) {
return profileDao.getProfileByUser(userId);
}
@Transactional
public void updateProfile(final Profile profile) {
List<Major> notApprovedMajors = extractNotApprovedMajors(profile);
List<Degree> notApprovedDegrees = extractNotApprovedDegrees(profile);
List<School> notApprovedSchools = extractNotApprovedSchools(profile);
List<Language> notApprovedLanguages = extractNotApprovedLanguages(profile);
List<Position> notApprovedPositions = extractNotApprovedPositions(profile);
List<Company> notApprovedCompanies = extractNotApprovedCompanies(profile);
List<Country> notApprovedCountries = extractNotApprovedCountries(profile);
List<City> notApprovedCities = extractNotApprovedCities(profile);
List<Certificate> notApprovedCertificates = extractNotApprovedCertificates(profile);
autoCompleteManager.updateAll(notApprovedMajors);
autoCompleteManager.updateAll(notApprovedDegrees);
autoCompleteManager.updateAll(notApprovedSchools);
autoCompleteManager.updateAll(notApprovedLanguages);
autoCompleteManager.updateAll(notApprovedPositions);
autoCompleteManager.updateAll(notApprovedCompanies);
autoCompleteManager.updateAll(notApprovedCountries);
autoCompleteManager.updateAll(notApprovedCities);
autoCompleteManager.updateAll(notApprovedCertificates);
profileDao.updateProfile(profile);
}
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
Profile persistedProfile = profileDao.findById(profileId);
if (persistedProfile.getContact() == null)
{
persistedProfile.setContact(new Contact());
}
List<Email> resultEmails = new ArrayList<Email>();
for (int i = 0; i < emails.size(); i++) {
if ((!userSecurityService.guaranteeUniquePrincipal(emails.get(i)) &&
!isPersistedInThePersistentCollection(emails.get(i), persistedProfile.getContact().getEmails())) ||
isDuplicateInTheCurrentCollection(emails.get(i), emails, i + 1)) {
resultEmails.add(emails.get(i));
}
}
return resultEmails;
}
private boolean isDuplicateInTheCurrentCollection(Email emailToCheck, List<Email> emails, int index)
{
for (int i = index ; i < emails.size(); i ++) {
if (emails.get(i).getEmailAddress().equals(emailToCheck.getEmailAddress())) {
return true;
}
}
return false;
}
private boolean isPersistedInThePersistentCollection(Email emailToCheck, Collection<Email> emails)
{
if (emails == null) {
return false;
}
for (Email persistedEmail : emails) {
if (persistedEmail.getEmailAddress().equalsIgnoreCase(emailToCheck.getEmailAddress())) {
return true;
}
}
return false;
}
}
同样重要的方法方法是 findDuplicateEmails
现在,在这个简短的背景之后,这是我的问题:
我正在将 Hibernate 与 spring 的 HibernateTemplate 一起使用。我发现在 findDuplicateEmails 方法中,来自 Flex 应用程序的一些全新实体会自动保存。这很奇怪,在调试过程中我发现即使我更改了ProfileManager中的方法findDuplicateEmails,它看起来像:
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
Email email = new Email();
return null;
}
实体电子邮件会自动保存。我还发现,如果实体的标识符不是“email”,而是其他内容,例如“newEmail”或“email1”或其他内容,则没有问题,并且当且仅当我创建它时,该实体才会被持久化执着的。这个问题只存在于这个类中,最后,这个问题只出现在电子邮件中。我的意思是,如果我有 Phone phone = new Phone();
实体电话仅在我希望时才会保留。
Flex 应用程序首先检查用户电子邮件中输入的内容是否唯一,然后在进行一些用户交互后,如果输入的数据有效,则调用方法 updateProfile()
。
I have already asked this question two times, but I'm new to stackoverflow and it seems that I don't know the rules for formatting my example code in here. Now I've decided to give the full stack of the calls and I hope I can explain the situation because everything is so strange and I can't find the words to describe it. First I will give you the source of the classes that have something to do with the problem. My actual question is in the end of the page. The large piece of code is just in case, because I don't know what could be the explanation of my problem.
Here is a service facade that gets calls from my flex application.
public class ServiceFacade implements IAuthenticationService, IProfileService, ICampaignService {
@Autowired
private IAuthenticationService authenticationService;
@Autowired
private IProfileService profileService;
@Autowired
private ICampaignService campaignService;
public void login(User user) throws AuthenticationException{
authenticationService.login(user);
}
@Override
public void logout() throws AuthenticationException {
authenticationService.logout();
}
@Override
public void sendForgottenPassword(String email) {
authenticationService.sendForgottenPassword(email);
}
@Override
public Profile getProfile(Long userId) {
return profileService.getProfile(userId);
}
@Override
public Profile updateProfile(Profile profile) {
return profileService.updateProfile(profile);
}
@Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileService.getSocialConnectionsTypes(userId);
}
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
return profileService.findDuplicateEmails(profileId, emails);
}
@Override
public Campaign getCampaign(Long campaignId) {
return campaignService.getCampaign(campaignId);
}
@Override
public Campaign updateCampaign(Campaign campaign) {
return campaignService.updateCampaign(campaign);
}
@Override
public void removeCampaign(Long campaignId) {
campaignService.removeCampaign(campaignId);
}
@Override
public void setPools(Long campaignId, Collection<Pool> pools) {
campaignService.setPools(campaignId, pools);
}
@Override
public void addPool(Long campaignId, Pool pool) {
campaignService.addPool(campaignId, pool);
}
@Override
public void removePool(Long campaignId, Pool pool) {
campaignService.removePool(campaignId, pool);
}
@Override
public List<Campaign> getCampaigns() {
return campaignService.getCampaigns();
}
@Override
public void updatePool(Long campaignId, Pool pool) {
campaignService.updatePool(campaignId, pool);
}
}
The method which is important for my question is the findDuplicateEmails method.
The profileService is implemented in the following class:
public class ProfileService implements IProfileService {
@Autowired
private IProfileManager profileManager;
@Override
public Profile getProfile(Long userId) {
return profileManager.getProfile(userId);
}
@Override
public Profile updateProfile(Profile profile){
profileManager.updateProfile(profile);
return profile;
}
@Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileManager.getSocialConnectionsTypes(userId);
}
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
return profileManager.findDuplicateEmails(profileId, emails);
}
}
Again the important method is findDuplicateEmails
The implementation of the profileManager is the following class:
public class ProfileManager implements IProfileManager {
@Autowired
private IProfileDao profileDao;
@Autowired
private ISectionManager autoCompleteManager;
@Autowired
private IUserSecurityService userSecurityService;
@Transactional
public Profile getProfile(Long userId) {
return profileDao.getProfileByUser(userId);
}
@Transactional
public void updateProfile(final Profile profile) {
List<Major> notApprovedMajors = extractNotApprovedMajors(profile);
List<Degree> notApprovedDegrees = extractNotApprovedDegrees(profile);
List<School> notApprovedSchools = extractNotApprovedSchools(profile);
List<Language> notApprovedLanguages = extractNotApprovedLanguages(profile);
List<Position> notApprovedPositions = extractNotApprovedPositions(profile);
List<Company> notApprovedCompanies = extractNotApprovedCompanies(profile);
List<Country> notApprovedCountries = extractNotApprovedCountries(profile);
List<City> notApprovedCities = extractNotApprovedCities(profile);
List<Certificate> notApprovedCertificates = extractNotApprovedCertificates(profile);
autoCompleteManager.updateAll(notApprovedMajors);
autoCompleteManager.updateAll(notApprovedDegrees);
autoCompleteManager.updateAll(notApprovedSchools);
autoCompleteManager.updateAll(notApprovedLanguages);
autoCompleteManager.updateAll(notApprovedPositions);
autoCompleteManager.updateAll(notApprovedCompanies);
autoCompleteManager.updateAll(notApprovedCountries);
autoCompleteManager.updateAll(notApprovedCities);
autoCompleteManager.updateAll(notApprovedCertificates);
profileDao.updateProfile(profile);
}
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
Profile persistedProfile = profileDao.findById(profileId);
if (persistedProfile.getContact() == null)
{
persistedProfile.setContact(new Contact());
}
List<Email> resultEmails = new ArrayList<Email>();
for (int i = 0; i < emails.size(); i++) {
if ((!userSecurityService.guaranteeUniquePrincipal(emails.get(i)) &&
!isPersistedInThePersistentCollection(emails.get(i), persistedProfile.getContact().getEmails())) ||
isDuplicateInTheCurrentCollection(emails.get(i), emails, i + 1)) {
resultEmails.add(emails.get(i));
}
}
return resultEmails;
}
private boolean isDuplicateInTheCurrentCollection(Email emailToCheck, List<Email> emails, int index)
{
for (int i = index ; i < emails.size(); i ++) {
if (emails.get(i).getEmailAddress().equals(emailToCheck.getEmailAddress())) {
return true;
}
}
return false;
}
private boolean isPersistedInThePersistentCollection(Email emailToCheck, Collection<Email> emails)
{
if (emails == null) {
return false;
}
for (Email persistedEmail : emails) {
if (persistedEmail.getEmailAddress().equalsIgnoreCase(emailToCheck.getEmailAddress())) {
return true;
}
}
return false;
}
}
Again the important method is the method findDuplicateEmails
Now, after this short background, here is my problem:
I am using Hibernate with spring's HibernateTemplate. I found out that in the method findDuplicateEmails, some completely new entities which come form the flex application gets saved automatically. This was very strange and during the debbugging I found out that even if I change the method findDuplicateEmails in the ProfileManager so it looks like:
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
Email email = new Email();
return null;
}
the entity email gets saved automatically. I also found out that if the identifier of the entity is not "email", but something else, like "newEmail", or "email1", or something, there is no problem and the entity gets persisted if and only if I make it persistent. This problem exists only in this class and finally, this problem shows up only for the Email. I mean that if I have Phone phone = new Phone();
the entity phone gets persisted only when I wish.
The flex application first checks that the entered from the user emails are unique, and then after some user interaction calls the method updateProfile()
if the entered data is valid.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我会下载 Hibernate 源代码并开始调试,您会在 Hibernate 中(发生)或在您的代码中发现错误,因为这是一种奇怪的行为。
这是我曾经得到过的建议,也是找到根源的最快、最有教育意义的方法。
I would download Hibernate sources and start debugging, you will either find a bug in Hibernate (happens) or in your code, as this is one weird behavior.
This is an advice I got once, and was the fastest, most educating way to get to the root.