I try to add a record to the database. In debug, I check to create object and object created is good. When I use getCurrentSession().save(entity); this doesn't add a record to the database but the session is open. I have a composite foreign key, to create this key I create an extra class.
class:
package nba_statistics.entities;
import org.hibernate.annotations.Cascade;
import javax.persistence.*;
#Entity(name = "PlayerMatchPositions")
#Table(name = "player_match_positions")
public class PlayerMatchPositions {
public void setId(PlayerMatchPositionsId id) {
this.id = id;
}
#EmbeddedId
private PlayerMatchPositionsId id;
#ManyToOne
#MapsId("player_id")
#Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
#JoinColumn(name = "player_id")
private Players player;
#ManyToOne
#MapsId("match_id")
#Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
#JoinColumn(name = "match_id")
private Matches match;
#ManyToOne
#MapsId("position_id")
#Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
#JoinColumn(name = "position_id")
private Positions position;
public PlayerMatchPositions(){};
public PlayerMatchPositions(Players player, Matches match, Positions position) {
id = new PlayerMatchPositionsId();
this.player = player;
this.match = match;
this.position = position;
}
public Players getPlayer() {
return player;
}
public void setPlayer(Players player) {
this.player = player;
}
public Matches getMatch() {
return match;
}
public void setMatch(Matches match) {
this.match = match;
}
public Positions getPosition() {
return position;
}
public void setPosition(Positions position) {
this.position = position;
}
#Override
public String toString() {
return "PlayerMatchPositions{" +
"id=" + id +
", player=" + player +
", match=" + match +
", position=" + position +
'}';
}
}
Extra class to foreign key:
package nba_statistics.entities;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;
import java.util.Objects;
#Embeddable
public
class PlayerMatchPositionsId implements Serializable {
#Column(name = "player_id")
int playerId;
#Column(name = "match_id")
int matchId;
#Column(name = "position_id")
int positionId;
public PlayerMatchPositionsId(){}
public PlayerMatchPositionsId(int playerId, int matchId, int positionId) {
this.playerId = playerId;
this.matchId = matchId;
this.positionId = positionId;
}
public int getPlayerId() {
return playerId;
}
public void setPlayerId(int playerId) {
this.playerId = playerId;
}
public int getMatchId() {
return matchId;
}
public void setMatchId(int matchId) {
this.matchId = matchId;
}
public int getPositionId() {
return positionId;
}
public void setPositionId(int positionId) {
this.positionId = positionId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PlayerMatchPositionsId)) return false;
PlayerMatchPositionsId that = (PlayerMatchPositionsId) o;
return Objects.equals(playerId, that.playerId) &&
Objects.equals(positionId, that.positionId)&&
Objects.equals(matchId, that.matchId);
}
#Override
public int hashCode() {
return Objects.hash(playerId, positionId, matchId);
}
}
Dao:
package nba_statistics.dao.classes;
import nba_statistics.dao.interfaces.IPlayerMatchPositionsDao;
import nba_statistics.entities.*;
public class PlayerMatchPositionsDao extends Dao implements IPlayerMatchPositionsDao {
public void persist(PlayerMatchPositions entity) {
getCurrentSession().save(entity);
}
#Override
public int getData(Players player, Matches match, Positions position){
if(player == null)
{
return 1;
}
if(match==null)
{
return 2;
}
if(position==null)
{
return 3;
}
PlayerMatchPositions playerMatchPositions = new PlayerMatchPositions();
playerMatchPositions.setPlayer(player);
playerMatchPositions.setMatch(match);
playerMatchPositions.setPosition(position);
playerMatchPositions.setId(new PlayerMatchPositionsId(player.getId(),match.getId(),position.getId()));
persist(playerMatchPositions);
return 0;
}
}
In other class, I do it similar and all is good, only in this class, it doesn't add to the database.
Related
I tried to implement custom TiledDataSource for using with paging library. When I used LivePagedListProvider like returns type for my Dao method it worked fine (after table items updating - ui updated automatically).
#Query("SELECT * FROM " + Table.States.PLAY_STATE + ", "+Table.Chart.ARTIST+ " ORDER BY position ASC")
LivePagedListProvider<Artist> loadArtists();
But when I try implement custom TiledDataSource for LivePagerListProvider table updates not triggered my observers.
Abstract generic class:
public abstract class PagedNetworkBoundResource<ResultType, RequestType> extends TiledDataSource<ResultType> {
#Override
public int countItems() {
return DataSource.COUNT_UNDEFINED;
}
#Override
public List<ResultType> loadRange(int startPosition, int count) {
fetchFromNetwork(startPosition, count);
return loadFromDb(startPosition, count);
}
#WorkerThread
private void fetchFromNetwork(int startPosition, int count) {
if (createCall(startPosition, count) != null)
try {
Response<RequestType> response = createCall(startPosition, count).execute();
if (response.isSuccessful() && response.code() == 200) {
saveCallResult(response.body());
}
} catch (IOException e) {
e.printStackTrace();
}
}
#WorkerThread
protected abstract void saveCallResult(#NonNull RequestType item);
#WorkerThread
protected abstract List<ResultType> loadFromDb(int startPosition, int count);
#WorkerThread
protected abstract Call<RequestType> createCall(int startPosition, int count);
public LiveData<PagedList<ResultType>> getAsLiveData() {
return new LivePagedListProvider<Integer, ResultType>() {
#Override
protected DataSource<Integer, ResultType> createDataSource() {
return PagedNetworkBoundResource.this;
}
}.create(0, new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPageSize(20)
.setInitialLoadSizeHint(20)
.build());
}
}
My dao method for this case:
#Query("SELECT * FROM " + Table.States.PLAY_STATE + ", "+Table.Chart.ARTIST+ " ORDER BY position ASC LIMIT (:limit) OFFSET (:offset)")
List<Artist> loadArtists(int offset, int limit);
I update Table.States.PLAY_STATE.
public void updatePlayerState(PlayerStateEntity state){
new Thread(() -> {
dao.deleteState();
dao.insertState(state);
}).run();
}
#Dao
public interface PlayStateDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
void insertState(PlayerStateEntity playEntity);
#Query("DELETE FROM " + Table.States.PLAY_STATE)
void deleteState();
#Query("SELECT * FROM "+Table.States.PLAY_STATE)
PlayerStateEntity getPlayerState();
}
#Entity(tableName = Table.States.PLAY_STATE)
public class PlayerStateEntity extends IdEntity {
#ColumnInfo(name = "album_played_id")
private Long albumPlayedId = -1L;
#ColumnInfo(name = "track_played_id")
private Long trackPlayedId = -1L;
#ColumnInfo(name = "artist_played_id")
private Long artistPlayedId = -1L;
#ColumnInfo(name = "state")
private PlayingState state;
#ColumnInfo(name = "playing_type")
private PlayingType playingType;
public Long getAlbumPlayedId() {
return albumPlayedId;
}
public void setAlbumPlayedId(Long albumPlayedId) {
this.albumPlayedId = albumPlayedId;
}
public Long getTrackPlayedId() {
return trackPlayedId;
}
public void setTrackPlayedId(Long trackPlayedId) {
this.trackPlayedId = trackPlayedId;
}
public Long getArtistPlayedId() {
return artistPlayedId;
}
public void setArtistPlayedId(Long artistPlayedId) {
this.artistPlayedId = artistPlayedId;
}
public PlayingState getState() {
return state;
}
public void setState(PlayingState state) {
this.state = state;
}
public PlayingType getPlayingType() {
return playingType;
}
public void setPlayingType(PlayingType playingType) {
this.playingType = playingType;
}
}
class Artist extends PlayEntity{
private String name;
private String link;
private String picture;
#ColumnInfo(name = "picture_small")
private String pictureSmall;
#ColumnInfo(name = "picture_medium")
private String pictureMedium;
#ColumnInfo(name = "picture_big")
private String pictureBig;
#ColumnInfo(name = "picture_xl")
private String pictureXl;
private Boolean radio;
private String tracklist;
private Integer position;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getPictureSmall() {
return pictureSmall;
}
public void setPictureSmall(String pictureSmall) {
this.pictureSmall = pictureSmall;
}
public String getPictureMedium() {
return pictureMedium;
}
public void setPictureMedium(String pictureMedium) {
this.pictureMedium = pictureMedium;
}
public String getPictureBig() {
return pictureBig;
}
public void setPictureBig(String pictureBig) {
this.pictureBig = pictureBig;
}
public String getPictureXl() {
return pictureXl;
}
public void setPictureXl(String pictureXl) {
this.pictureXl = pictureXl;
}
public Boolean getRadio() {
return radio;
}
public void setRadio(Boolean radio) {
this.radio = radio;
}
public String getTracklist() {
return tracklist;
}
public void setTracklist(String tracklist) {
this.tracklist = tracklist;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
#Override
public boolean isItemPlaying() {
return getId() == getArtistPlayedId().longValue() && getPlayingType() == PlayingType.Artist && getState() == PlayingState.Playing;
}
}
public abstract class PlayEntity extends PlayerStateEntity {
public abstract boolean isItemPlaying();
}
public class ArtistsRepository {
private final ChartArtistDao chartArtistDao;
private final DeezerService deezerService;
#Inject
public ArtistsRepository(ChartArtistDao chartArtistDao, DeezerService deezerService) {
this.chartArtistDao = chartArtistDao;
this.deezerService = deezerService;
}
public LiveData<PagedList<ChartArtistDao.Artist>> getArtist() {
return new PagedNetworkBoundResource<ChartArtistDao.Artist, ModelList<ChartArtistEntity>>() {
#Override
protected void saveCallResult(#NonNull ModelList<ChartArtistEntity> item) {
if (item != null) {
chartArtistDao.saveArtists(item.getItems());
}
}
#Override
protected List<ChartArtistDao.Artist> loadFromDb(int startPosition, int count) {
return chartArtistDao.loadArtists(startPosition, count);
}
#Override
protected Call<ModelList<ChartArtistEntity>> createCall(int startPosition, int count) {
return deezerService.getChartArtist(startPosition, count);
}
}.getAsLiveData();
}
}
For each Artist items I add fields from PlayerStateEntity (not good solution but this easy way to represent state of ui items). After PlayerStateEntity table updates Room should notify about data changes, but doesn't do it.
I understand that Room doesn't know about query what I used, and can't updates my RecyclerView which provide by paging library. But maybe some one knows how to notify Room about tables which I used inside mine DataSource for future triggering ui updates?
The problem was related with custom DataSource realization. When data has changed, LivePagedListProvider should create a new DataSource instance for right ui updating. I used the same instance, so my previous solution is not right.
I only need to get first name and last name into attribute ownerName and for me the best solution would be if I just call the setter for ownerName in setter of conversationOwner but with this I am getting error:
Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: Exception occurred inside setter of medictonproject.model.ConversationEntity.conversationOwner
Here is the Entity class:
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.*;
import org.hibernate.annotations.CascadeType;
import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "conversation", schema = "swprojekt")
public class ConversationEntity {
private int conversationId;
private String title;
private Timestamp beginningDate;
#JsonIgnore
private UserEntity conversationOwner;
private String ownerName;
#JsonIgnore
private List<MessageEntity> messages = new ArrayList<>();
private MessageEntity firstMessage;
private boolean seen;
#Transient
public MessageEntity getFirstMessage() {
return firstMessage;
}
public void setFirstMessage(MessageEntity firstMessage) {
this.firstMessage = firstMessage;
}
#Transient
public boolean isSeen() {
return seen;
}
public void setSeen( boolean seen ) {
this.seen = seen;
}
#OneToMany(mappedBy="conversation", cascade = javax.persistence.CascadeType.ALL)
public List<MessageEntity> getMessages() {
return messages;
}
public void setMessages(List<MessageEntity> messages) {
this.messages = messages;
}
#ManyToOne(fetch=FetchType.LAZY, cascade = javax.persistence.CascadeType.ALL)
#JoinColumn(name="user_id")
public UserEntity getConversationOwner() {
return conversationOwner;
}
public void setConversationOwner(UserEntity conversationOwner) {
this.conversationOwner = conversationOwner;
setOwnerName();
}
#Transient
public String getOwnerName() {
return ownerName;
}
public void setOwnerName() {
this.ownerName = conversationOwner.getFirstName() + " " + conversationOwner.getLastName();
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "conversation_id", nullable = false)
public int getConversationId() {
return conversationId;
}
public void setConversationId(int conversationId) {
this.conversationId = conversationId;
}
#Basic
#Column(name = "title", nullable = false, length = 200)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Basic
#Column(name = "beginning_date", nullable = false)
public Timestamp getBeginningDate() {
return beginningDate;
}
public void setBeginningDate(Timestamp beginningDate) {
this.beginningDate = beginningDate;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConversationEntity that = (ConversationEntity) o;
if (conversationId != that.conversationId) return false;
if (title != null ? !title.equals(that.title) : that.title != null) return false;
if (beginningDate != null ? !beginningDate.equals(that.beginningDate) : that.beginningDate != null)
return false;
return true;
}
#Override
public int hashCode() {
int result = conversationId;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (beginningDate != null ? beginningDate.hashCode() : 0);
return result;
}
}
I have an entity question and an entity test with ManyToMany relationship between the two entitie.
when I want to view the questions of a test this error is occurred.
failed to lazily initialize a collection of role:
tn.esen.entities.Test.questions, could not initialize proxy - no Session
this is the JPA implementation of the two entities.
Question:
package tn.esen.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
#Entity
public class Question implements Serializable {
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((contenu == null) ? 0 :
contenu.hashCode());
result = prime * result + ((dateCreation == null) ? 0 :
dateCreation.hashCode());
result = prime * result + ((niveauDeDifficulte == null) ? 0 :
niveauDeDifficulte.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Question other = (Question) obj;
if (contenu == null) {
if (other.contenu != null)
return false;
} else if (!contenu.equals(other.contenu))
return false;
if (dateCreation == null) {
if (other.dateCreation != null)
return false;
} else if (!dateCreation.equals(other.dateCreation))
return false;
if (niveauDeDifficulte == null) {
if (other.niveauDeDifficulte != null)
return false;
} else if (!niveauDeDifficulte.equals(other.niveauDeDifficulte))
return false;
return true;
}
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_question")
private int id;
private String contenu;
private String niveauDeDifficulte;
private Date dateCreation;
#OneToMany(mappedBy="question",fetch = FetchType.EAGER)
private Collection <Reponse> reponses;
#ManyToOne
private Categorie categorie;
#ManyToOne
private Administrateur administrateur;
#ManyToMany(mappedBy = "questions",fetch = FetchType.EAGER)
private Collection<Test> tests;
public Question(){
super();
}
#Override
public String toString() {
return "Question [id=" + id + ", contenu=" + contenu + ",
niveauDeDifficulte=" + niveauDeDifficulte + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContenu() {
return contenu;
}
public void setContenu(String contenu) {
this.contenu = contenu;
}
public String getNiveauDeDifficulte() {
return niveauDeDifficulte;
}
public void setNiveauDeDifficulte(String niveauDeDifficulte) {
this.niveauDeDifficulte = niveauDeDifficulte;
}
public Date getDateCreation() {
return dateCreation;
}
public void setDateCreation(Date dateCreation) {
this.dateCreation = dateCreation;
}
public Collection<Reponse> getReponses() {
return reponses;
}
public void setReponses(Collection<Reponse> reponses) {
this.reponses = reponses;
}
public Categorie getCategorie() {
return categorie;
}
public void setCategorie(Categorie categorie) {
this.categorie = categorie;
}
public Administrateur getAdministrateur() {
return administrateur;
}
public void setAdministrateur(Administrateur administrateur) {
this.administrateur = administrateur;
}
public Collection<Test> getTest() {
return tests;
}
public void setTest(Collection<Test> tests) {
this.tests = tests;
}
public Question(String contenu, String niveauDeDifficulte, Date
dateCreation) {
super();
this.contenu = contenu;
this.niveauDeDifficulte = niveauDeDifficulte;
this.dateCreation = dateCreation;
}
Test:
package tn.esen.entities;
#Entity
public class Test implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String duree;
private String typeDePreparation;
private String lieu;
private int nbrQuestionFacile;
private int nbrQuestionMoyen;
private int nbrQuestionDifficle;
#OneToMany(mappedBy = "test")
private Collection<Resultat> resultats;
#ManyToMany
private Collection<Question> questions;
#ManyToOne
private ResponsableTechnique responsableTechnique;
public Test() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDuree() {
return duree;
}
public void setDuree(String duree) {
this.duree = duree;
}
public Collection<Question> getQuestions() {
return questions;
}
public void setQuestions(Collection<Question> questions) {
this.questions = questions;
}
public Test(String duree, String typeDePreparation, String lieu, int
nbrQuestionFacile, int nbrQuestionMoyen,
int nbrQuestionDifficle) {
super();
this.duree = duree;
this.typeDePreparation = typeDePreparation;
this.lieu = lieu;
this.nbrQuestionFacile = nbrQuestionFacile;
this.nbrQuestionMoyen = nbrQuestionMoyen;
this.nbrQuestionDifficle = nbrQuestionDifficle;
}
public ResponsableTechnique getRésponsableTechnique() {
return responsableTechnique;
}
public void setRésponsableTechnique(ResponsableTechnique
résponsableTechnique) {
this.responsableTechnique = résponsableTechnique;
}
public String getTypeDePreparation() {
return typeDePreparation;
}
public void setTypeDePreparation(String typeDePreparation) {
this.typeDePreparation = typeDePreparation;
}
public String getLieu() {
return lieu;
}
public void setLieu(String lieu) {
this.lieu = lieu;
}
public int getNbrQuestionFacile() {
return nbrQuestionFacile;
}
public void setNbrQuestionFacile(int nbrQuestionFacile) {
this.nbrQuestionFacile = nbrQuestionFacile;
}
public int getNbrQuestionMoyen() {
return nbrQuestionMoyen;
}
public void setNbrQuestionMoyen(int nbrQuestionMoyen) {
this.nbrQuestionMoyen = nbrQuestionMoyen;
}
public int getNbrQuestionDifficle() {
return nbrQuestionDifficle;
}
public void setNbrQuestionDifficle(int nbrQuestionDifficle) {
this.nbrQuestionDifficle = nbrQuestionDifficle;
}
public Collection<Resultat> getResultats() {
return resultats;
}
public void setRésultats(Collection<Resultat> resultats) {
this.resultats = resultats;
}
}
}
When you get Test and access Test.questions later, after leaving the transaction, you will get a lazy initialization exception when the Test entity is detached and questions has not been initialized/fetched yet. You can either do a specific fetch, or depending on your configuration, you can call Test.getQuestions().size() before you exit the transaction.
References: How to solve lazy initialization exception using JPA and Hibernate as provider
LazyInitializationException in JPA and Hibernate
Hibernate LazyInitializationException using Spring CrudRepository
I've been stuck here for almost a week trying find the answer on the internet but sadly nothing worked. :( Everytime I try to update using this method:
private Tenant updateTenantWithApplicationProperties(List<TenantApplicationProperty> newTenantApplicationProperties, String tenantId) {
String reason = "Update application properties.";
Tenant existingTenant = tenantRepository.findById(tenantId);
List<TenantApplicationProperty> temp = existingTenant.getTenantApplicationProperties();
existingTenant.setTenantApplicationProperties(newTenantApplicationProperties);
setApplicationPropertiesUpdateValues(temp, existingTenant);
if(newTenantApplicationProperties != null && newTenantApplicationProperties.size() != 0) {
Tenant savedTenantWithAppProps = saveTenantWithLog(existingTenant, reason);
return savedTenantWithAppProps;
}
return existingTenant;
}
Im always getting this error:
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.infor.ecom.tenant.manager.model.entity.ApplicationProperty
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1361)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1289)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1295)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:876)
But when Im using this method it works fine:
public Tenant updateTenant(Tenant tenant) {
List<Database> databases = tenant.getDatabases();
List<Administrator> administrators = tenant.getAdministrators();
validateUpdateTenant(tenant);
validateDatabases(databases);
validateAdministrators(administrators);
Tenant existingTenant = findByIdWithAllDetails(tenant.getId());
List<Database> listExistingDatabases = existingTenant.getDatabases();
Database existingEcomDb = getDatabaseByType(listExistingDatabases,
TenantManagerConstants.ECOM_DATASOURCE);
setDatabaseUpdateValues(listExistingDatabases, tenant);
setAdministratorsUpdateValues(existingTenant.getAdministrators(),
tenant);
setProductUpdateValue(existingTenant.getProduct(), tenant);
setApplicationPropertiesUpdateValues(existingTenant.getTenantApplicationProperties(), tenant);
setEcomDBParamsDefaultValues(tenant);
setAdministratorDefaultValues(tenant);
Database updateEcomDb = getDatabaseByType(tenant.getDatabases(),
TenantManagerConstants.ECOM_DATASOURCE);
Boolean shouldInstallNewDB = true;
if (existingEcomDb.getName().equalsIgnoreCase(updateEcomDb.getName())
&& existingEcomDb.getHost().equalsIgnoreCase(
updateEcomDb.getHost())
&& existingEcomDb.getPort().equals(updateEcomDb.getPort())) {
shouldInstallNewDB = false;
} else {
testEcomDBConnection(updateEcomDb);
}
int ecomDbTableCount = getEcomDBTableCount(updateEcomDb);
String[][] languages = formatAndValidateLanguages(updateEcomDb
.getEcomDatabaseParameters().getLanguages());
Tenant updatedTenant = saveExistingTenant(tenant);
if (updatedTenant != null) {
if (shouldInstallNewDB || ecomDbTableCount == 0) {
installDatabase(updateEcomDb, languages, updatedTenant);
} else {
updateDatabase(updateEcomDb, languages, updatedTenant);
}
storageService.updateTenantFolderStructure(updatedTenant);
} else {
throw new TenantManagerException(
ApiMessageConstants.M_TENANT_PROVISION_ERROR,
ApiMessageConstants.C_TENANT_PROVISION_ERROR);
}
return updatedTenant;
}
So here is my complete codes:
Tenant.java
package com.infor.ecom.tenant.manager.model.entity;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import com.infor.ecom.tenant.manager.constant.TenantManagerConstants;
import com.infor.ecom.tenant.manager.constant.TenantStatusEnum;
#Entity
#Table(name="tenant")
#XmlRootElement(name = "Tenant",namespace = "http://com.infor.ecom.tenant.manager/Tenant")
public class Tenant extends BaseModel {
private static final long serialVersionUID = -6687293822212120396L;
#Id
private String id;
private String displayName;
private String description;
private String url;
private String apiKey;
private String status;
#OneToMany(mappedBy = "tenant", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Database> databases;
#OneToMany(mappedBy = "tenant", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Activity> activites;
#OneToMany(mappedBy = "tenant", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Administrator> administrators;
private String message;
#OneToMany(mappedBy = "tenant", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<TenantApplicationProperty> tenantApplicationProperties;
#OneToOne(mappedBy = "tenant", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private Product product;
public Database findEcomDatabase() {
Database database = null;
if(databases != null) {
for(Database db : databases) {
if(db.getDatasource() != null) {
if(TenantManagerConstants.ECOM_DATASOURCE.equals(db.getDatasource().getName())) {
database = db;
break;
}
}
}
}
return database;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
public String getStatus() {
return status;
}
public void setStatus(TenantStatusEnum statusEnum) {
this.status = statusEnum.name();
}
public List<Database> getDatabases() {
return databases;
}
public void setDatabases(List<Database> databases) {
this.databases = databases;
}
public void addDatabase(Database database) {
if (this.databases == null) {
this.databases = new ArrayList<Database>();
}
database.setTenant(this);
this.databases.add(database);
}
public List<Activity> getActivites() {
return activites;
}
public void setActivites(List<Activity> activities) {
this.activites = activities;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void setStatus(String status) {
this.status = status;
}
public List<Administrator> getAdministrators() {
return this.administrators;
}
public void setAdministrators(List<Administrator> administrators) {
for (Administrator admin:administrators) {
admin.setTenant(this);
}
this.administrators = administrators;
}
public void addAdministrator(Administrator administrator) {
if (this.administrators == null) {
this.administrators = new ArrayList<Administrator>();
}
administrator.setTenant(this);
this.administrators.add(administrator);
}
public List<TenantApplicationProperty> getTenantApplicationProperties() {
return tenantApplicationProperties;
}
public void setTenantApplicationProperties(
List<TenantApplicationProperty> tenantApplicationProperties) {
this.tenantApplicationProperties = tenantApplicationProperties;
}
public void addTenantApplicationProperty(TenantApplicationProperty tenantApplicationProperty) {
if (this.tenantApplicationProperties == null) {
this.tenantApplicationProperties = new ArrayList<TenantApplicationProperty>();
}
tenantApplicationProperty.setTenant(this);
this.tenantApplicationProperties.add(tenantApplicationProperty);
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
product.setTenant(this);
this.product = product;
}
}
TenantApplicationProperty.java
package com.infor.ecom.tenant.manager.model.entity;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import com.infor.ecom.tenant.manager.model.entity.pk.TenantApplicationPropertyPK;
#Entity
#Table(name = "tenant_application_property")
#IdClass(TenantApplicationPropertyPK.class)
public class TenantApplicationProperty extends BaseModel {
private static final long serialVersionUID = 1L;
#Id
#ManyToOne
#JoinColumn(name = "tenant_id")
private Tenant tenant;
#Id
#OneToOne
#JoinColumn(name = "application_property_id")
private ApplicationProperty applicationProperty;
private String value;
public TenantApplicationProperty() {
super();
}
/**
* Added constructor to handle custom query for
* findByTenantIdApplicationPropertyName. No need to retrieve Tenant and
* ApplicationProperty
*
* #param value
*/
public TenantApplicationProperty(String value) {
setTenant(null);
setApplicationProperty(null);
setValue(value);
}
public Tenant getTenant() {
return tenant;
}
public void setTenant(Tenant tenant) {
this.tenant = tenant;
}
public ApplicationProperty getApplicationProperty() {
return applicationProperty;
}
public void setApplicationProperty(ApplicationProperty applicationProperty) {
this.applicationProperty = applicationProperty;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((applicationProperty == null) ? 0 : applicationProperty
.hashCode());
return result;
}
#Override
public boolean equals(Object object) {
if (this == object)
return true;
if (object == null)
return false;
if (getClass() != object.getClass())
return false;
TenantApplicationProperty tenantAppProp = (TenantApplicationProperty) object;
if (applicationProperty == null) {
if (tenantAppProp.applicationProperty != null) {
return false;
}
} else if (!applicationProperty.getApplicationPropertyGroup().getName().equals(tenantAppProp.applicationProperty.getApplicationPropertyGroup().getName())
|| !applicationProperty.getName().equals(tenantAppProp.applicationProperty.getName())) {
return false;
}
return true;
}
}
TenanatApplicationPropertyPK.java
package com.infor.ecom.tenant.manager.model.entity.pk;
public class TenantApplicationPropertyPK implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String tenant;
private Integer applicationProperty;
public String getTenantId() {
return tenant;
}
public void setTenantId(String tenant) {
this.tenant = tenant;
}
public Integer getApplicationPropertyId() {
return applicationProperty;
}
public void setApplicationPropertyId(Integer applicationProperty) {
this.applicationProperty = applicationProperty;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((applicationProperty == null) ? 0 : applicationProperty
.hashCode());
result = prime * result + ((tenant == null) ? 0 : tenant.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
TenantApplicationPropertyPK tenantAppPropPK = (TenantApplicationPropertyPK) obj;
if (applicationProperty == null) {
if (tenantAppPropPK.applicationProperty != null) {
return false;
}
} else if (!applicationProperty
.equals(tenantAppPropPK.applicationProperty)) {
return false;
}
if (tenant == null) {
if (tenantAppPropPK.tenant != null) {
return false;
}
} else if (!tenant.equals(tenantAppPropPK.tenant)) {
return false;
}
return true;
}
}
ApplicationProperty.java
package com.infor.ecom.tenant.manager.model.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "application_property")
public class ApplicationProperty extends BaseModel {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String defaultValue;
private boolean isVisible;
private boolean clientVisible;
#OneToOne
#JoinColumn(name = "property_group_id")
private ApplicationPropertyGroup applicationPropertyGroup;
#OneToOne
#JoinColumn(name = "property_type_id")
private ApplicationPropertyType applicationPropertyType;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public boolean getIsVisible() {
return isVisible;
}
public void setIsVisible(boolean isVisible) {
this.isVisible = isVisible;
}
public boolean getClientVisible() {
return clientVisible;
}
public void setClientVisible(boolean clientVisible) {
this.clientVisible = clientVisible;
}
public ApplicationPropertyGroup getApplicationPropertyGroup() {
return applicationPropertyGroup;
}
public void setApplicationPropertyGroup(ApplicationPropertyGroup applicationPropertyGroup) {
this.applicationPropertyGroup = applicationPropertyGroup;
}
public ApplicationPropertyType getApplicationPropertyType() {
return applicationPropertyType;
}
public void setApplicationPropertyType(ApplicationPropertyType applicationPropertyType) {
this.applicationPropertyType = applicationPropertyType;
}
}
ApplicationPropertyGroup.java
package com.infor.ecom.tenant.manager.model.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "application_property_group")
public class ApplicationPropertyGroup extends BaseModel {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ApplicationPropertyType.java
package com.infor.ecom.tenant.manager.model.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "application_property_type")
public class ApplicationPropertyType extends BaseModel {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
TenantServiceImpl.java
private Tenant updateTenantWithApplicationProperties(List<TenantApplicationProperty> newTenantApplicationProperties, String tenantId) {
String reason = "Update application properties.";
Tenant existingTenant = tenantRepository.findById(tenantId);
List<TenantApplicationProperty> temp = existingTenant.getTenantApplicationProperties();
existingTenant.setTenantApplicationProperties(newTenantApplicationProperties);
setApplicationPropertiesUpdateValues(temp, existingTenant);
if(newTenantApplicationProperties != null && newTenantApplicationProperties.size() != 0) {
Tenant savedTenantWithAppProps = saveTenantWithLog(existingTenant, reason);
return savedTenantWithAppProps;
}
return existingTenant;
}
private Tenant saveTenantWithLog(Tenant tenant, String reason) {
Tenant updatedTenant = tenantRepository.save(tenant);
TenantLog tenantLog = new TenantLog();
tenantLog.setTenantId(updatedTenant.getId());
tenantLog.setDisplayName(updatedTenant.getDisplayName());
tenantLog.setDescription(updatedTenant.getDescription());
tenantLog.setUrl(updatedTenant.getUrl());
tenantLog.setApiKey(updatedTenant.getApiKey());
tenantLog.setStatus(TenantStatusEnum.valueOf(updatedTenant.getStatus()));
tenantLog.setReason(reason);
tenantLog.setMessage(updatedTenant.getMessage());
tenantLogRepository.save(tenantLog);
return updatedTenant;
}
private void setApplicationPropertiesUpdateValues(List<TenantApplicationProperty> existingTenantAppProps, Tenant tenant) {
List<TenantApplicationProperty> newTenantApplicationProperties = (tenant.getTenantApplicationProperties() != null) ? tenant.getTenantApplicationProperties() : new ArrayList<TenantApplicationProperty>();
if(newTenantApplicationProperties.size() != 0) {
for(TenantApplicationProperty tenantAppProp : newTenantApplicationProperties) {
int index = existingTenantAppProps.indexOf(tenantAppProp);
if (index < 0) {
// throw an error -- tenantAppProp should always exist, right?
} else {
existingTenantAppProps.get(index).setValue(tenantAppProp.getValue());
}
}
tenant.setTenantApplicationProperties(existingTenantAppProps);
}
}
public Tenant updateTenant(Tenant tenant) {
List<Database> databases = tenant.getDatabases();
List<Administrator> administrators = tenant.getAdministrators();
validateUpdateTenant(tenant);
validateDatabases(databases);
validateAdministrators(administrators);
Tenant existingTenant = findByIdWithAllDetails(tenant.getId());
List<Database> listExistingDatabases = existingTenant.getDatabases();
Database existingEcomDb = getDatabaseByType(listExistingDatabases,
TenantManagerConstants.ECOM_DATASOURCE);
setDatabaseUpdateValues(listExistingDatabases, tenant);
setAdministratorsUpdateValues(existingTenant.getAdministrators(),
tenant);
setProductUpdateValue(existingTenant.getProduct(), tenant);
setApplicationPropertiesUpdateValues(existingTenant.getTenantApplicationProperties(), tenant);
setEcomDBParamsDefaultValues(tenant);
setAdministratorDefaultValues(tenant);
Database updateEcomDb = getDatabaseByType(tenant.getDatabases(),
TenantManagerConstants.ECOM_DATASOURCE);
Boolean shouldInstallNewDB = true;
if (existingEcomDb.getName().equalsIgnoreCase(updateEcomDb.getName())
&& existingEcomDb.getHost().equalsIgnoreCase(
updateEcomDb.getHost())
&& existingEcomDb.getPort().equals(updateEcomDb.getPort())) {
shouldInstallNewDB = false;
} else {
testEcomDBConnection(updateEcomDb);
}
int ecomDbTableCount = getEcomDBTableCount(updateEcomDb);
String[][] languages = formatAndValidateLanguages(updateEcomDb
.getEcomDatabaseParameters().getLanguages());
Tenant updatedTenant = saveExistingTenant(tenant);
if (updatedTenant != null) {
if (shouldInstallNewDB || ecomDbTableCount == 0) {
installDatabase(updateEcomDb, languages, updatedTenant);
} else {
updateDatabase(updateEcomDb, languages, updatedTenant);
}
storageService.updateTenantFolderStructure(updatedTenant);
} else {
throw new TenantManagerException(
ApiMessageConstants.M_TENANT_PROVISION_ERROR,
ApiMessageConstants.C_TENANT_PROVISION_ERROR);
}
return updatedTenant;
}
private Tenant saveExistingTenant(Tenant tenant) {
tenant.setStatus(TenantStatusEnum.INPROGRESS);
tenant.setMessage(ApiMessageConstants.M_DATABASE_UPDATE_INPROGRESS);
String reason = ApiMessageConstants.R_UPDATE_TENANT;
return saveTenantWithLog(tenant, reason);
}
In application property, you defined 1-1 relation like:
#OneToOne
#JoinColumn(name = "property_group_id")
private ApplicationPropertyGroup applicationPropertyGroup;
#OneToOne
#JoinColumn(name = "property_type_id")
private ApplicationPropertyType applicationPropertyType;
While you have not defined the same relation (note it should work bidirectionally i.e. say for e.g. if you as a person related to an employee id, then employee id is related to you as a person well) in individual property ApplicationPropertyGroup and ApplicationPropertyType.
You should add the same 1-1 relation in ApplicationPropertyGroup and ApplicationPropertyType with ApplicationProperty.
Good day! I'm having a problem when updating an entity. When I click the "update" button, the changes are saved. However, when I go a different page, the recently changed (or added) items are there but the old items (that should be changed or removed) are also there. Particularly the relatedTags (the name and notes are updating just fine). Why is it not persistent or permanent?
Here is where the updating happens.
Form<Tag> filledForm = tagForm.fill(Tag.find.byId(id)).bindFromRequest();
Tag editedTag = RelatedTag.findTag(id);
if(filledForm.hasErrors()) {
return badRequest(editTagForm.render(user, editedTag, filledForm, tags));
}
else {
List<RelatedTag> relatedTagsAlloc = new ArrayList<RelatedTag>();
java.util.Map<String, String[]> map = request().body().asFormUrlEncoded();
String[] relatedTags = map.get("relatedTags.tag.name");
String[] relationship = map.get("relatedTags.relationship");
String[] relatedNotes = map.get("relatedTags.relatedNotes");
if (relatedTags != null) {
for (int i = 0; i < relatedTags.length; i++) {
if (RelatedTag.exists(relatedTags[i].trim().toLowerCase().replaceAll("\\s+", " "))) {
relatedTagsAlloc.add(RelatedTag.findByLabel(
relatedTags[i].trim().toLowerCase().replaceAll("\\s+", " "), relationship[i], relatedNotes[i].trim()));
} else {
Tag unknown = new Tag(relatedTags[i], "");
Tag.create(unknown);
relatedTagsAlloc.add(RelatedTag.findByLabel(
relatedTags[i].trim().toLowerCase().replaceAll("\\s+", " "), relationship[i], relatedNotes[i].trim()));
}
}
editedTag.getRelatedTags().clear();
}
editedTag.setName(filledForm.get().getName().toLowerCase().replaceAll("\\s+", " "));
editedTag.setRelatedTags(relatedTagsAlloc);
editedTag.update();
Application.log(user, editedTag, action);
writeToFile(editedTag);
return ok(summary.render(user, editedTag));
}
And here are the models:
Tag model:
package models;
import java.sql.Timestamp;
import java.util.*;
import javax.persistence.*;
import javax.validation.*;
import play.data.Form;
import play.data.validation.Constraints.*;
import play.db.ebean.*;
import play.db.ebean.Model.Finder;
import scala.Int;
#Entity
public class Tag extends Model{
#Id
private int id;
#Required
#MaxLength(value=100)
#Column(unique=true)
private String name;
#MaxLength(value=200)
private String notes;
#OneToMany(cascade=CascadeType.ALL)
public List<RelatedTag> relatedTags = new ArrayList<RelatedTag>();
#Version
public Timestamp lastUpdate;
public static Finder<Integer, Tag> find = new Finder(Int.class, Tag.class);
public Tag() {
}
public Tag(String name, String notes){
this.name = name;
this.notes = notes;
}
public Tag(int id, String name, String notes, List<RelatedTag> relatedTags) {
this.id = id;
this.name = name;
this.notes = notes;
this.relatedTags = relatedTags;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public List<RelatedTag> getRelatedTags() {
return relatedTags;
}
public void setRelatedTags(List<RelatedTag> relatedTags) {
this.relatedTags = relatedTags;
}
public static List<Tag> all() {
return find.all();
}
public static void create(Tag tag){
tag.save();
}
public static void delete(int id){
find.ref(id).delete();
}
public static void update(int id, Tag tag) {
tag.update(id); // updates this entity, by specifying the entity ID
}
public static boolean exists(Tag newTag) {
for(Tag allTags : Tag.find.all()) {
if(allTags.getName().equals(newTag.getName()))
return true;
}
return false;
}
}
RelatedTag model
package models;
import java.sql.Timestamp;
import java.util.*;
import javax.persistence.*;
import javax.validation.*;
import play.data.Form;
import play.data.validation.Constraints.*;
import play.db.ebean.*;
import play.db.ebean.Model.Finder;
import scala.Int;
#Entity
public class RelatedTag extends Model {
#Id
public int rtID;
private int id; //same as Tag's id
private String relationship;
private String relatedNotes;
#Version
public Timestamp lastUpdate;
public RelatedTag() {}
public RelatedTag(int id, String relationship, String relatedNotes) {
this.id = id;
this.relationship = relationship;
this.relatedNotes = relatedNotes;
}
public void setId(int id){
this.id = id;
}
public void setRelationship(String relationship){
this.relationship = relationship;
}
public void setRelatedNotes(String relatedNotes) {
this.relatedNotes = relatedNotes;
}
public int getId(){
return id;
}
public String getRelationship(){
return relationship;
}
public String getRelatedNotes() {
return relatedNotes;
}
public static void create(List<RelatedTag> rt){
((Model) rt).save();
}
public static boolean exists(String tagRelated) {
for(Tag tag : Tag.find.all()) {
if(tagRelated.equals(tag.getName()))
return true;
}
return false;
}
public static RelatedTag findByLabel(String tagRelated, String relation, String relatedNotes) {
RelatedTag relatedTag = null;
for(Tag tag : Tag.find.all()) {
if(tagRelated.equals(tag.getName())) {
relatedTag = new RelatedTag(tag.getId(), relation, relatedNotes);
}
}
return relatedTag;
}
public static Tag findTag(int id) {
for(Tag tag : Tag.find.all()) {
if(id == tag.getId())
return tag;
}
return null;
}
}
What have I been doing wrong? Please help me fix this. Thank you very much!