tag:blogger.com,1999:blog-703334580972056124.post6322371668994686108..comments2017-08-01T05:46:19.533-07:00Comments on My Java Comments: Using GWT and Hibernate (JPA)Miroslav Nociarhttp://www.blogger.com/profile/12444795644246923174noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-703334580972056124.post-36742424750622301502013-12-14T10:47:02.658-08:002013-12-14T10:47:02.658-08:00Hello Vladimir,
the question asked is for sure rel...Hello Vladimir,<br />the question asked is for sure relevant, but I am afraid that there is no easy answer. The process of modification of a JPA record in a GWT application is: <br />1) get a cloned entity (with some cloned relation properties) <br />2) modify the cloned entity on the client side<br />3) merge the modified entity on the server side<br /><br />The merging of the modified entity can be sometimes easy like calling the EntityManager#merge(T entity). But the problem is if the entity contains some relations with the cascade property. For example a company with a collection of employees and partners (or many more):<br /><br />@Entity<br />public class Company<br />..@OneToMany(cascade=ALL)<br />..private List employees;<br />..@OneToMany(cascade=ALL)<br />..private List partners;<br />}<br /><br />If you want to update just a company record, you can implement your service like this:<br /><br />public MyServiceImpl implements MyService {<br />..EntityManager em;<br /><br />..Company getById(long id) {<br />....Company company = em.find(Company.class, id);<br />....return JpaCloner.clone(company); // employees and partners are left as null<br />..}<br /><br />..long save(Company company) {<br />....Company merged;<br />....if (company.getId() == null) {<br />......company.setEmployees(new ArrayList()); // set empty list<br />......company.setPartners(new ArrayList()); // set empty list<br />......em.persist(company);<br />......merged = company;<br />....} else {<br />......// restore the employees from the DB<br />......Company original = em.find(Company.class, company.getId());<br />......company.setEmployees(original.getEmployees());<br />......company.setPartners(original.getPartners());<br />......merged = em.merge(company);<br />....}<br />....em.flush();<br />....return merged.getId();<br />..}<br />}<br /><br />But now I see that this approach is not very friendly for progragrammers. It could be better to have a new method in the JpaCloner class like:<br />public static void copy(T entity1, T entity2) {...}<br /><br />This method will copy all basic properties (i.e. columns) from entity1 to entity2. This method could be used for merging of basic properties from a modified detached JPA entity to an attached JPA entity. The save method can be rewritten like:<br /><br />..long save(Company company) {<br />....Company merged;<br />....if (company.getId() == null) {<br />......company.setEmployees(new ArrayList()); // set empty list<br />......em.persist(company);<br />......merged = company;<br />....} else {<br />......Company original = em.find(Company.class, company.getId());<br />......JpaCloner.copy(company, original); // copy just basic properties, not relations<br />......merged = original;<br />....}<br />....em.flush();<br />....return merged.getId();<br />..}<br /><br /><br />What is your opinion Vladimir?Miroslav Nociarhttps://www.blogger.com/profile/12444795644246923174noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-43208592634500732122013-12-10T01:31:02.219-08:002013-12-10T01:31:02.219-08:00please recommend a way to restore from cloned obje...please recommend a way to restore from cloned object original JPA enity,<br />so we can save it, to update DB record.<br />Problem sems to be in nulls on not cloned properties which will saved if to apply persist for cloned object.<br /><br />As well, is there way to restory hierancy of original oject with updated changes from cloned objects ?<br /><br />thanks<br /><br /><br />Anonymoushttps://www.blogger.com/profile/00613739924607136124noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-71843132707079504232013-12-10T01:22:43.993-08:002013-12-10T01:22:43.993-08:00This comment has been removed by the author.Anonymoushttps://www.blogger.com/profile/00613739924607136124noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-83653938672487935732013-10-29T03:08:20.968-07:002013-10-29T03:08:20.968-07:00Hello, JPA Cloner can be used only in a server sid...Hello, JPA Cloner can be used only in a server side code. Please note that the project heavily uses Java Reflection Framework. JPA Cloner allows to easily transport JPA entities from server side to GWT client side. Once you have a JPA entity on the client, you can modify it and send to an RPC procedure like:<br /><br />class MyServiceImpl extends RemoteService implements MyService {<br />....public void saveEntity(MyEntity entity) {<br />........// TODO save the entity in DB<br />....}<br />....public MyEntity getEntity(Long id) {<br />........MyEntity entity = dao.get(id);<br />........return JpaCloner.clone(entity, "some.properties");<br />....}<br /><br />}<br /><br />That's all :-)Miroslav Nociarhttps://www.blogger.com/profile/12444795644246923174noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-83356269388771472852013-10-28T04:17:07.360-07:002013-10-28T04:17:07.360-07:00Hallo,
how works JPA Cloner in the direction Clie...Hallo, <br />how works JPA Cloner in the direction Client->Server. for example to save a entityAnonymoushttps://www.blogger.com/profile/13966364849825729837noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-81771570348429150172013-08-23T14:50:49.501-07:002013-08-23T14:50:49.501-07:00That´s good. Just did. Let´s make it better!! Than...That´s good. Just did. Let´s make it better!! Thanks again.Meu Butiquimhttps://www.blogger.com/profile/06098694510415411968noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-29738397328943506552013-08-23T13:52:21.233-07:002013-08-23T13:52:21.233-07:00Hi,
I think that you have discovered a JPA cloner ...Hi,<br />I think that you have discovered a JPA cloner bug :-) The cloning do not correctly handle @EmbeddedId annotation, only the @Embedded annotation. Please create an issue on https://github.com/nociar/jpa-cloner. I will try to fix it ASAP.<br /><br />btw: the correct cloning pattern for your case is "userDomains.domain" (will be correctly handled when after the fix)Miroslav Nociarhttps://www.blogger.com/profile/12444795644246923174noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-88119299385064552982013-08-23T13:34:28.110-07:002013-08-23T13:34:28.110-07:00// CLIENT METHOD
public User tryLogin(String userN...// CLIENT METHOD<br />public User tryLogin(String userName, String userPasswd) {<br /><br /> try {<br /> <br /> EntityManager em = factory.createEntityManager();<br /> em.getTransaction().begin();<br /> User user = em.createQuery( "from User u where u.login = :asd", User.class ).setParameter("asd", userName).getSingleResult();<br /> <br /> if (user==null) {<br /><br /> System.out.println("login:" + userName + " nao encontrado");<br /> return null;<br /> <br /> } else {<br /> <br /> System.out.println("id:"+user.getId()+" email:"+user.getEmail());<br /> <br /> MessageDigest md = MessageDigest.getInstance("MD5"); <br /> md.update(userPasswd.getBytes()); <br /> BigInteger hash = new BigInteger(1, md.digest()); <br /> String userEncripPasswd = hash.toString(16); <br /> <br /><br /> if(!user.getEncripPassword().equals(userEncripPasswd)){<br /> System.out.println("password does not match");<br /> return null;<br /> }<br /> <br /> user.setLastLogin(new Date());<br /> user.setLoginsQty(user.getLoginsQty()+1);<br /> <br /> //options i´ve tryed<br /> //JpaCloner.clone(user, "userDomains.pk.domain.attrs");<br /> //JpaCloner.clone(user, "userDomains.(domain).attrs");<br /> //JpaCloner.clone(user, "userDomain*.domain.attrs");<br /> //JpaCloner.clone(user, "userDomains.(domain$).attrs");<br /> //JpaCloner.clone(user, "userDomains.domain.attr*");<br /> //JpaCloner.clone(user, "userDomains.domain.attrs.columnName");<br /> //JpaCloner.clone(user, "userDomains");<br /> //JpaCloner.clone(user, "userDomains.domain.attrs");<br /> //JpaCloner.clone(user, "userDomains.domain.attrs.columnName");<br /> //JpaCloner.clone(user, "userDomains.attrs");<br /> //JpaCloner.clone(user, "userDomains.domain");<br /><br /><br /> User clonedUser = JpaCloner.clone(user, "userDomains");<br /> <br /> em.getTransaction().commit();<br /> em.close()<br /> <br /> return clonedUser;<br /> <br /> }<br /> <br /><br /> } catch (Exception e) {<br /> <br /> System.out.println(ExceptionUtils.getStackTrace(e));<br /> return null;<br /> } <br /> <br /><br /> <br />}Meu Butiquimhttps://www.blogger.com/profile/06098694510415411968noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-64040569424935341102013-08-23T13:34:00.949-07:002013-08-23T13:34:00.949-07:00//UserDomain
@SuppressWarnings("serial")...//UserDomain<br />@SuppressWarnings("serial")<br />@Entity<br />@Table(name = "Users_X_Domain")<br />@AssociationOverrides({<br /> @AssociationOverride(name = "pk.user", joinColumns = @JoinColumn(name = "user_id")),<br /> @AssociationOverride(name = "pk.domain", joinColumns = @JoinColumn(name = "domain_id")) })<br />@Access(AccessType.FIELD)<br />public class UserDomain implements Serializable {<br /> <br /> @EmbeddedId<br /> private UserDomainPk pk = new UserDomainPk();<br /> <br /> //additional attribute!!<br /> @Type(type="com.webradar.nethandle.model.profile.enums.EnumUserDomainUserType")<br /> @Column(name="type_id")<br /> private EnumUserDomain enumUserDomain;<br /><br /> <br /> //helper method<br /> public User getUser() {<br /> return getPk().getUser();<br /> }<br /> <br /> public void setUser(User user) {<br /> getPk().setUser(user);<br /> }<br /><br /> //helper method<br /> public Domain getDomain() {<br /> return getPk().getDomain();<br /> }<br /><br /> public void setDomain(Domain domain) {<br /> getPk().setDomain(domain);<br /> }<br /> <br /> <br /> public boolean equals(Object o) {<br /> if (this == o)<br /> return true;<br /> if (o == null || getClass() != o.getClass())<br /> return false;<br /> <br /> UserDomain that = (UserDomain) o;<br /> <br /> if (getPk() != null ? !getPk().equals(that.getPk())<br /> : that.getPk() != null)<br /> return false;<br /> <br /> return true;<br /> }<br /> <br /> public int hashCode() {<br /> return (getPk() != null ? getPk().hashCode() : 0);<br /> } <br /> <br /> <br /> public UserDomainPk getPk() {<br /> return pk;<br /> }<br /><br /><br /> public void setPk(UserDomainPk pk) {<br /> this.pk = pk;<br /> }<br /><br /><br /> public EnumUserDomain getEnumUserDomain() {<br /> return enumUserDomain;<br /> }<br /><br /><br /> public void setEnumUserDomain(EnumUserDomain enumUserDomain) {<br /> this.enumUserDomain = enumUserDomain;<br /> } <br /><br />}<br /><br />//UserDomainPk<br />@SuppressWarnings("serial")<br />@Embeddable<br />@Access(AccessType.FIELD)<br />public class UserDomainPk implements Serializable {<br /><br /> @ManyToOne<br /> private User user;<br /> <br /> @ManyToOne<br /> private Domain domain;<br /> <br /> <br /> public boolean equals(Object o) {<br /> if (this == o) return true;<br /> if (o == null || getClass() != o.getClass()) return false;<br /> <br /> UserDomainPk that = (UserDomainPk) o;<br /> <br /> if (user != null ? !user.equals(that.user) : that.user != null) return false;<br /> if (domain != null ? !domain.equals(that.domain) : that.domain != null) return false;<br /> <br /> return true;<br /> }<br /> <br /> public int hashCode() {<br /> int result;<br /> result = (user != null ? user.hashCode() : 0);<br /> result = 31 * result + (domain != null ? domain.hashCode() : 0);<br /> return result;<br /> }<br /><br /> public User getUser() {<br /> return user;<br /> }<br /><br /> public void setUser(User user) {<br /> this.user = user;<br /> }<br /><br /> public Domain getDomain() {<br /> return domain;<br /> }<br /><br /> public void setDomain(Domain domain) {<br /> this.domain = domain;<br /> }<br /><br />}<br /><br />//persistence.xml : relevant part<br />com.mypackage.User<br />com.mypackage.Domain<br />com.mypackage.UserDomain<br />com.mypackage.UserDomainPk<br />Meu Butiquimhttps://www.blogger.com/profile/06098694510415411968noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-75998346144415816372013-08-23T13:32:21.267-07:002013-08-23T13:32:21.267-07:00Here we go. Thanks again for your attention. I´m t...Here we go. Thanks again for your attention. I´m trying to get rid of Gilead.<br />I followed the instructions in http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/ to make may M:N relationship with an extre column<br /><br />//Domain<br />@SuppressWarnings("serial")<br />@Entity<br />@Table(name="Domain")<br />@Access(AccessType.FIELD)<br />public class Domain implements Serializable {<br /> <br /> @Id<br /> @GeneratedValue(strategy = GenerationType.IDENTITY)<br /> private Long id;<br /> <br /> @Column(name="name")<br /> private String name;<br /> <br /> <br /> @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.domain", cascade=CascadeType.ALL)<br /> private List userDomains = new ArrayList(0);<br /><br /><br /> public Long getId() {<br /> return id;<br /> }<br /><br /><br /> public void setId(Long id) {<br /> this.id = id;<br /> }<br /><br /><br /> public String getName() {<br /> return name;<br /> }<br /><br /><br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /><br /><br /> public List getUserDomains() {<br /> return userDomains;<br /> }<br /><br /><br /> public void setUserDomains(List userDomains) {<br /> this.userDomains = userDomains;<br /> }<br /><br />}<br /><br /><br />//User<br />@SuppressWarnings("serial")<br />@Entity<br />@Table(name="Users", uniqueConstraints=@UniqueConstraint(columnNames={"login"}))<br />@Access(AccessType.FIELD)<br />public class User implements Serializable {<br /> <br /> @Id<br /> @GeneratedValue(strategy = GenerationType.IDENTITY)<br /> private Long id;<br /> <br /> private String login;<br /> <br /> private String name;<br /> <br /> private String email;<br /> <br /> private String encripPassword;<br /> <br /> @Temporal(TemporalType.TIMESTAMP)<br /> private Date lastLogin;<br /> <br /> private int loginsQty;<br /> <br /> <br /> @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user")<br /> private List userDomains = new ArrayList(0);<br /> <br /> <br /> public User() {}<br /> <br /> public User(Long id, String name, String email) {<br /> this.id = id;<br /> this.name = name;<br /> this.email = email;<br /> }<br /><br /> public Long getId() {<br /> return id;<br /> }<br /><br /> public void setId(Long id) {<br /> this.id = id;<br /> }<br /><br /> public String getName() {<br /> return name;<br /> }<br /><br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /><br /> public String getEmail() {<br /> return email;<br /> }<br /><br /> public void setEmail(String email) {<br /> this.email = email;<br /> }<br /><br /><br /><br /> public String getLogin() {<br /> return login;<br /> }<br /><br /> public void setLogin(String login) {<br /> this.login = login;<br /> }<br /><br /> public Date getLastLogin() {<br /> return lastLogin;<br /> }<br /><br /> public void setLastLogin(Date lastLogin) {<br /> this.lastLogin = lastLogin;<br /> }<br /><br /> public int getLoginsQty() {<br /> return loginsQty;<br /> }<br /><br /> public void setLoginsQty(int loginsQty) {<br /> this.loginsQty = loginsQty;<br /> }<br /><br /> public String getEncripPassword() {<br /> return encripPassword;<br /> }<br /><br /> public void setEncripPassword(String encripPassword) {<br /> this.encripPassword = encripPassword;<br /> }<br /><br /> public List getUserDomains() {<br /> return userDomains;<br /> }<br /><br /> public void setUserDomains(List userDomains) {<br /> this.userDomains = userDomains;<br /> }<br /> <br />}Meu Butiquimhttps://www.blogger.com/profile/06098694510415411968noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-21238601949925919112013-08-23T09:40:51.108-07:002013-08-23T09:40:51.108-07:00Hmm, this sounds strange. It seems that the Domain...Hmm, this sounds strange. It seems that the Domain entity is not cloned, but just copied. But this cannot happen if the class is annotated by @Entity or @Embedded. Could you try to check? If not, please paste the mapped classes of User, UserDomain and Domain (all classes involved in cloning). thxMiroslav Nociarhttps://www.blogger.com/profile/12444795644246923174noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-4414698999230330582013-08-22T11:56:09.277-07:002013-08-22T11:56:09.277-07:00Actually I believe that the cloning process is goi...Actually I believe that the cloning process is going ok (I can see the hibernate selects in the log). My method ends like:<br /><br />User clonedUser = JpaCloner.clone(user, "userDomains.domain");<br /><br />em.getTransaction().commit();<br />em.close();<br /><br />return clonedUser ;<br /><br />and then I get the exception below:<br />15:52:10,466 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/nethandle]] (http--127.0.0.1-8080-2) Exception while dispatching incoming RPC call: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.webradar.nethandle.model.profile.Domain.userDomains, no session or session was closed<br /> at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:393) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]<br /> at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:385) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]<br /> at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:378) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]<br /> at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:112) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]<br /> at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:500) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]<br /> at java.lang.String.valueOf(String.java:2854) [rt.jar:1.7.0_21]<br /> at java.lang.StringBuilder.append(StringBuilder.java:128) [rt.jar:1.7.0_21]<br /> at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:667) [gwt-servlet-2.5.1.jar:]<br /> at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126) [gwt-servlet-2.5.1.jar:]<br /> at <br /><br /><br />and so on...Meu Butiquimhttps://www.blogger.com/profile/06098694510415411968noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-29554717829309903772013-08-22T00:59:26.473-07:002013-08-22T00:59:26.473-07:00Hello,
the JpaCloner supports @Entity and @Embedda...Hello,<br />the JpaCloner supports @Entity and @Embeddable objects, just specify them in the patterns like:<br />return JpaCloner.clone(user, "userDomains.domain", "userDomains.userProfile");<br /><br />After the cloinng the lazy exceptions cannot be thrown by GWT-RPC serialization (as the cloned entities are not proxy classes). But please note that the cloning should be done in a *transaction scope*! Can you check this?Miroslav Nociarhttps://www.blogger.com/profile/12444795644246923174noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-53163200117691784642013-08-21T16:41:21.081-07:002013-08-21T16:41:21.081-07:00I mean, I ma using JpaCloner.clone(user, "use...I mean, I ma using JpaCloner.clone(user, "userDomains.domain") and getting the exception I wrote above. tksMeu Butiquimhttps://www.blogger.com/profile/06098694510415411968noreply@blogger.comtag:blogger.com,1999:blog-703334580972056124.post-29217014958275252472013-08-21T16:33:58.460-07:002013-08-21T16:33:58.460-07:00Hello,
I have 2 hibernate entities (User and Domai...Hello,<br />I have 2 hibernate entities (User and Domain) mapped in a M:N relationship, with bi directionality. I also need a extra attribute (status) in the relationship class "UserProfile" witch is mapped with @Embeddable and @EmbeddedId. Can JpaCloner help me? I am using "userDomains.domain" but GWT is complaining about a lazy exception with "Domain.userDomains". Thank you.Meu Butiquimhttps://www.blogger.com/profile/06098694510415411968noreply@blogger.com