From 9ea1080fb3b14a23fb294260db418e0ea840eafd Mon Sep 17 00:00:00 2001 From: Leonard <Leonard@Leonard.Leo> Date: Mon, 15 Jun 2020 01:42:50 +0300 Subject: [PATCH] quite a bit of work --- core/database.mv.db | Bin 36864 -> 122880 bytes .../resources/META-INF/persistence.xml | 9 +- .../Communication/Client.java | 35 +++++- .../ClientControllerCommunicator.java | 42 +++++-- .../Model/Map/Planet.java | 9 +- .../Model/Map/Trader.java | 16 +-- .../galaxytruckerreloaded/Model/Ship.java | 5 +- .../Server/Persistence/TraderDAOTest.java | 111 ++++++++++++++++++ .../main/resources/META-INF/persistence.xml | 9 +- exceptions.md | 7 ++ 10 files changed, 213 insertions(+), 30 deletions(-) create mode 100644 core/src/com/galaxytrucker/galaxytruckerreloaded/Test/Server/Persistence/TraderDAOTest.java create mode 100644 exceptions.md diff --git a/core/database.mv.db b/core/database.mv.db index 9dbdffc5c5d72fd1cf5f84151e6d3282d8f5cb4f..ca641dab7b3779b5718bac20e7526a27f31ae4fa 100644 GIT binary patch literal 122880 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 literal 36864 zcmeHQ%WvDr9hPJ(o7#1Opf8|kQm)#K?N%^2!?$jVB-=`C$(7`dbE%gvZH#p+*H(hG zDB5KEK>vZ>dMeQWrH7si6zH)iP!!l}fu8!~JV=V79<jWRqKpnEt)VnC-wes$H{Zvf zc1yVEoc7$$__lrWbH9XSSuVOypPzkJLTb^y@a?|um5_lg8%mJu6}!EQXLi4YiZA?& z%ah(&a9sD)@4HX^i;}7Pvg(-bN=Cc{0s;YnfIvVXAP^7;2m}NI0s(=5KtLcM5SRl5 zb~*3oTfzV5U{pjC1Ofs9fq+0jARrJB2nYlO0s;YnfIvVXaJ>kGB0o0)ocf^U7oXYZ zB^+#CmQ=6;ocS;NC8Kz5f9hXC=|!*CFKOTefEPAE`R|`R^GmAj$X(BhIRd1aUf>>B z`pMGYGGEW!Cav5;i0@#&qkKS%{5-UH3*8F-Vwr9bc~2pKRq|IOfAz1P+0Xo~)1Fhc z`}QjTXWu>#_gjAVo8<l8xqsHVu+J`Sw+}9dOZw5i?VS2sa{M3VYvlOnXI^iw_bId_ zz-UW(on-(c=CV+V6yVd77ydq=D;I;k0|Kl}U`HN-omemk?kdAwp}4CsAOO4TYYcZo zkzx1w+4D>AXwX6MqCr5fcoVqML!I1&E@^_xM_ywsz^nyk&;n#4OQ$1mm|digYyrMx z7$^(_Eztl4>WNTblP>_{Wy#=8FcVFHw!zEsEe?W(O*`tf@+(@W&#KgisvN2jxwO+t zV!AWf71n8+cUm)jWRL2!Po_^PIeqR1lcYqakHUO4A9Di@{vIg}r%<w7A@hxWS|)R~ z1e2K0+h8B&Ej@@$?yR0wvsxBql^m9H7_F)lH>_Ludaonm+XMmv0fB%(Kp-Fx5C{ka z1Oftq$p|oNq=qK^G(WwiAlLM5eI`1c`r(xk^b~k>>54=&>;OuwaoRV5{pbIXzqhoS zL0C~W-N@h0e<i<?U(IIjEPp87KWf)HQl(WZcWTEE4(oeW30W2t6{N!2@3OQ&I&9Zk zQhi%$G&@r5sNU|hr9!LO>=dMSd9Nd_TV2ODyN0QFO4ra-e_h%ww|Av=!%!_CwVIDr zPwg6pZY#2*>kdNL(+&8DX=~Wf9c*c?rn~S|gyw5Ld;>OQWZQUMDp&XGjo-e4mz2A+ z{C!DU`v-4SrCiyqRi#e(!Cp-&92`E_t5*tJ1!(f)!p2H~PoZ8dNcBdiwgb%%+TJ+a z+bhzda=YEE)S=hapmPQ3<8rIATW)P&P1|ILR1RCMTB8FU-7iQF>Wy;iNxXQs27TWh zS;2n!Xu=VV@_ucw;+4%`^RE6t`f#nv;6G^9_n~s>QSC{rqwL*dc=s3;q-G;lMnMSr zzxkSf<44j*YnRYuz#<hhz`80`nvHg+RR+-F-xj_ZR1|B?2B`rcuGWrX#}Bp)CewWw zw@+AS#thqWyHoD8`QQb8I36>C^k6=|E1OWyI@I&~3G;&tH=7^9{_rRyr^;S)XQx)J zH((Mpn|rl#BY8mZHSOK{!N4pb4cdTFd^q(e;>0M@rWV3h23_2QQT$o@D3Zgc8bzpR zU=*Vo#*QT}e9kA+520hntYgXH-+uJadbD$}eXy+@G_=Quo%a5d_KzQzJCBrOa_ljj zmP6B(4?a18gK^*d4X^A+(C5Eq(>qOO37ZNdC-9gS6{PKEt5)A>1ZUSqRQV7PW4<Hm zRjamLgKI{m1{cW06^WiIjV4^QDv#izyt1U;y_LxaeS9V5=~<em_~z+VAWs3v)5~AB zlBE~z#X|$SrUkd7w{?XIpj`<Xa1*l{DpP~HuI&O(CkCBIOLvxo>G7Y%I9ZYxmcjc9 zT!qQGM7z9L*9RC=C72|OAMk)Ub$<IO^PNzflDQPcwp}7NQAr9JM3O=#-B@&E(~U<C z9H~>CoO%AsEt85(*DPAa6)Yx;QE|dZ$XOo{ISUzV>oIxjr;I+xA$^%r-3moTWl&Tk z+7_r=dZ_DQ4{4FEBcI=puESZ3-=h_FSr3hbkQ7(0n0`lfB%Lc))?g16uE2m|Mr2dX zl93bkkm`;@!qIof2uDu5P*12v1BFI<A)8^z!h2)oC?+&9DRe3|Du?WtAcc$^GIPkv zA#at7Ye>ecRNq9V<LPWam=5}6D*a9#F~q<5#6u{0p5B5p!gOqPTJAjkah(4rwPC{l zucQKp?Z?x%BJIe4|DWdnIn4jz?lOx0&lmfDAMS$J7!JO@F#3jg{=CurJImM1^4~Ve zzZo91h+%ssv+U$vWbQ@5EH_x8D@V07xb^9V2E!>a?phFJY|#h=F-O&0M7)CmFy;X; z3w(chLxC@Ibp-~iC`Lr`#ZcHVW!(LyuCnlMj&3~g{>9A%-l+(`J5l(cXACD|c!X#W z&(E)+;y1UH<xqEI9G^q}U?@*KbBi3lzmuFpG+H1a5SR}H*o{2m-{Bn>$M`=&s_A~2 z`hU`z9q@lVqXj#S)ldH(@c-N=xqmO^ss1lm{~U?^3&Hwf0sp_*dzo*ga2`&6@Hq10 z#R(3U$1mbv^Sb>YIYEQ};`f%La5*BnnogueGp=z8R&;hbK_{5RP{uzK^X3F4CNaP> zFUSi>N$jx~vfe;di?NDV;+zuvpGGQQ`U6!w{_zF>57H_-GoD?7|IbI9FIpiG5C{ka zk_a&VAMtN~|3gZQ|6{D1o^4Lgo~J#M>Ho>QI+6dc^gJ|gzCUdX(vPF+|Nn&gKi8)J zg;)m=>VKyech$!X;BnvTM328v|LHS4?0JCE&ohiM<i9Obf9C$J;<vMz{O5oA;*Vh8 zy|qktGRxlbU$PH9Tk$WSf=A%bx!0My8MY{9v8~Ov4%@nHOKq)F_+K5mkminBL7Q8P zKw?dR5mt*iMW;x!qLGXv@RK?;!A>H_38rS)E<9mIouUu~V2x)S(M(s4jIkE0+@9Wu ztCPw@BQDSJ!m|5dF5U9%KHyt*tn|ulR=L9}Pv&<?@yOE3NA{e0WTT!dE_RLd${l9V zby?-+WP`3VnCOKYba|o|l350sVWJnsRb4YQ=(?;vkJUFtLZ5^oSWg&&=`dqGGz6PY z*AMIS(lg1#J-^9JG6SC9YcvGYmAVmLf(Z*1?wc><<&ZPVY2Xgn45)h;YzAmiUBXG$ zApRE!2m}@Zf#j-s$e$zj@0lJ}QP)Uk%Co)8{r?)foAJk6i2hIW|BXt)rqTPB)8!F@ zYQyvKesrfq+Kg=z4gjezr;qzD1oH<6z~8fS<{O~{ASJ&fw*sh))rdrsbDU_B>;KVe z>LmStR*w@;Z5icnnONh@Sye@9%OG#-pv(`cE!q7D^3jUamWvP>i9QGf1Ofs9fq+0@ zaS>qpf5gA}0sv&a=$`t0_o;tTvQ*VJyS6(UpHBNU=l^<Q^_=j3x=0Ue@l>AR>*Op8 zyv7ouW4>-3@PEa3!<B0^W4=P_0r;2j00<8NPmefSRE_fgT_x3@@Bj!80HlJPGQZzq zW&p?+moTXNe8FqnS{Oe@OIs9UKf;2Es*e@AQRzmb8~vS=`o+(=gmDReKUUfJ%3c(i zO}Vl+gI+S9D|>?v@StQ40cGq1JX*Xo=|w;TrOE7Myp*K_N!F{4f3!ing5dz`IjqGO z7I6;4FXyPiFXzy3H~6_LVKP`;IwpE15V%nU82^v>cX*%GWBgy!TuZiR^wg*F|NjH* CN)Gh^ diff --git a/core/out/production/resources/META-INF/persistence.xml b/core/out/production/resources/META-INF/persistence.xml index 4c58c808..7c239e2d 100644 --- a/core/out/production/resources/META-INF/persistence.xml +++ b/core/out/production/resources/META-INF/persistence.xml @@ -4,8 +4,15 @@ version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="database" transaction-type="RESOURCE_LOCAL"> - <class>com.galaxytrucker.galaxytruckerreloaded.Model.User</class> <class>com.galaxytrucker.galaxytruckerreloaded.Model.Crew.Crew</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.ShipLayout.Room</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.ShipLayout.System</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Map.Trader</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Map.Overworld</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Map.Planet</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Weapons.Weapon</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Ship</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.User</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:h2:./database;DB_CLOSE_ON_EXIT=FALSE;" /> <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" /> diff --git a/core/src/com/galaxytrucker/galaxytruckerreloaded/Communication/Client.java b/core/src/com/galaxytrucker/galaxytruckerreloaded/Communication/Client.java index b05b700b..d1203a3c 100644 --- a/core/src/com/galaxytrucker/galaxytruckerreloaded/Communication/Client.java +++ b/core/src/com/galaxytrucker/galaxytruckerreloaded/Communication/Client.java @@ -1,12 +1,15 @@ package com.galaxytrucker.galaxytruckerreloaded.Communication; +import com.galaxytrucker.galaxytruckerreloaded.Model.Ship; import com.galaxytrucker.galaxytruckerreloaded.Server.RequestObject; import com.galaxytrucker.galaxytruckerreloaded.Server.ResponseObject; +import lombok.Getter; import lombok.NonNull; import java.io.*; import java.net.Socket; +/** This class handles the client-side networking */ public class Client { /** @@ -34,16 +37,25 @@ public class Client { */ private ObjectInputStream receiveObject; + /** + * The client's ship + */ + @Getter + private Ship myShip; + /** * Send a request to the server + * + * @param requestObject - the request object * @return the server's response + * + * @throws IllegalArgumentException on exception */ public ResponseObject sendAndReceive(RequestObject requestObject) throws IllegalArgumentException { try { sendObject.writeObject(requestObject); return (ResponseObject) receiveObject.readObject(); - } - catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); throw new IllegalArgumentException(e.getMessage()); } @@ -51,11 +63,23 @@ public class Client { /** * Login + * + * @param username - the username of the user to login + * + * @return whether the client is allowed to login or not + * + * @throws IllegalArgumentException on error */ public boolean login(String username) throws IllegalArgumentException { try { send.println("[LOGIN]:" + username); - return receive.readLine().equals("[ACCEPTED]"); + boolean successfulLogin = receive.readLine().equals("true"); + if (successfulLogin) { + send.println("[GIVE-ME-SHIP]"); + myShip = (Ship) receiveObject.readObject(); + return true; + } + return false; } catch (Exception e) { e.printStackTrace(); throw new IllegalArgumentException(e.getMessage()); @@ -64,6 +88,11 @@ public class Client { /** * Constructor + * + * @param ipAddress - the ipAddress of the server + * @param port - the server port + * + * @throws IllegalArgumentException on error */ public Client(@NonNull String ipAddress, @NonNull int port) throws IllegalArgumentException { try { diff --git a/core/src/com/galaxytrucker/galaxytruckerreloaded/Communication/ClientControllerCommunicator.java b/core/src/com/galaxytrucker/galaxytruckerreloaded/Communication/ClientControllerCommunicator.java index 0d38b459..e7884b27 100644 --- a/core/src/com/galaxytrucker/galaxytruckerreloaded/Communication/ClientControllerCommunicator.java +++ b/core/src/com/galaxytrucker/galaxytruckerreloaded/Communication/ClientControllerCommunicator.java @@ -3,29 +3,49 @@ package com.galaxytrucker.galaxytruckerreloaded.Communication; import com.galaxytrucker.galaxytruckerreloaded.Model.Map.Overworld; import com.galaxytrucker.galaxytruckerreloaded.Model.Map.Planet; import com.galaxytrucker.galaxytruckerreloaded.Model.Ship; -import lombok.Getter; -import lombok.Setter; +import com.galaxytrucker.galaxytruckerreloaded.Server.RequestObject; +import com.galaxytrucker.galaxytruckerreloaded.Server.ResponseObject; +import lombok.*; @Setter @Getter +@RequiredArgsConstructor(access = AccessLevel.PUBLIC) public class ClientControllerCommunicator { - /** Client ship */ + /** + * Client ship + */ private Ship clientShip; private Overworld map; private Planet currentPlanet; - /** Issue a new request and receive a response + /** + * Client class + */ + @NonNull + private Client client; + + /** + * Issue a new request and receive a response + * * @param request - the request - * @return the server's response */ - public String sendRequest(String request){ - return null; + * @return the server's response + */ + public ResponseObject sendRequest(RequestObject request) throws IllegalArgumentException { + return client.sendAndReceive(request); } - /** Issue login request + /** + * Issue login request + * * @param username - the username - * @return true if the user already exists else create a enw spaceship */ - public boolean login(String username){ - return false; + * @return true if the user already exists else create a enw spaceship + */ + public boolean login(String username) { + boolean permittedLogin = client.login(username); + if (permittedLogin) { + clientShip = client.getMyShip(); + } + return permittedLogin; } } diff --git a/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Map/Planet.java b/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Map/Planet.java index 4e0a1a2d..9d9ec737 100644 --- a/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Map/Planet.java +++ b/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Map/Planet.java @@ -5,10 +5,7 @@ import com.galaxytrucker.galaxytruckerreloaded.Model.Ship; import lombok.*; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; +import javax.persistence.*; import java.io.Serializable; import java.util.List; @@ -58,4 +55,8 @@ public class Planet implements Serializable { /** Trader */ @OneToOne private Trader trader; + + /** The overWorld this planet belongs to */ + @ManyToOne + private Overworld overworld; } diff --git a/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Map/Trader.java b/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Map/Trader.java index ce267d3b..fce3efc8 100644 --- a/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Map/Trader.java +++ b/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Map/Trader.java @@ -5,9 +5,7 @@ import com.galaxytrucker.galaxytruckerreloaded.Model.Crew.Crew; import com.galaxytrucker.galaxytruckerreloaded.Model.Weapons.Weapon; import lombok.*; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.OneToMany; +import javax.persistence.*; import java.io.Serializable; @Getter @@ -15,18 +13,20 @@ import java.io.Serializable; @Entity @RequiredArgsConstructor(access = AccessLevel.PUBLIC) @NoArgsConstructor(access = AccessLevel.PUBLIC) -public class Trader extends Planet implements Serializable { +public class Trader implements Serializable { /** ID */ - @Id + @NonNull @Id private int id; - /** Associated user */ + /** Planet the trader is located at */ + @OneToOne (cascade = CascadeType.ALL) + @NonNull private Planet planet; /** Weapons for sale */ @NonNull - @OneToMany + @OneToMany (cascade = CascadeType.ALL) private List<Weapon> weaponStock; /** Rockets for sale */ @@ -38,7 +38,7 @@ public class Trader extends Planet implements Serializable { private int fuelStock; /** Crew for sale */ - @OneToMany + @OneToMany (cascade = CascadeType.ALL) @NonNull private List<Crew> crewStock; diff --git a/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Ship.java b/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Ship.java index a6c8b61e..e7d6e5de 100644 --- a/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Ship.java +++ b/core/src/com/galaxytrucker/galaxytruckerreloaded/Model/Ship.java @@ -78,6 +78,7 @@ public class Ship implements Serializable { * The planet the ship is currently at */ @NonNull + @ManyToOne private Planet planet; /** Shields */ @@ -92,12 +93,12 @@ public class Ship implements Serializable { /** This ship's systems */ @NonNull - @ElementCollection + @OneToMany private List<Room> systems; /** Inventory */ @NonNull - @ElementCollection + @OneToMany private List<Weapon> inventory; /** Whether or not the ship is in combat */ diff --git a/core/src/com/galaxytrucker/galaxytruckerreloaded/Test/Server/Persistence/TraderDAOTest.java b/core/src/com/galaxytrucker/galaxytruckerreloaded/Test/Server/Persistence/TraderDAOTest.java new file mode 100644 index 00000000..de577e1b --- /dev/null +++ b/core/src/com/galaxytrucker/galaxytruckerreloaded/Test/Server/Persistence/TraderDAOTest.java @@ -0,0 +1,111 @@ +package com.galaxytrucker.galaxytruckerreloaded.Test.Server.Persistence; + +import com.galaxytrucker.galaxytruckerreloaded.Model.Crew.Crew; +import com.galaxytrucker.galaxytruckerreloaded.Model.Map.Overworld; +import com.galaxytrucker.galaxytruckerreloaded.Model.Map.Planet; +import com.galaxytrucker.galaxytruckerreloaded.Model.Map.PlanetEvent; +import com.galaxytrucker.galaxytruckerreloaded.Model.Map.Trader; +import com.galaxytrucker.galaxytruckerreloaded.Model.Ship; +import com.galaxytrucker.galaxytruckerreloaded.Model.Weapons.Weapon; +import com.galaxytrucker.galaxytruckerreloaded.Server.Database.Database; +import com.galaxytrucker.galaxytruckerreloaded.Server.Persistence.TraderDAO; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.persistence.EntityManager; +import java.util.ArrayList; +import java.util.Random; +import java.util.UUID; + +/** + * Test the trader database access object + */ +public class TraderDAOTest { + + /** + * EntityManager + */ + private EntityManager entityManager = Database.getEntityManager(); + + /** + * Trader DAO + */ + private TraderDAO traderDAO = new TraderDAO(); + + /** + * Test adding a new trader to the database + */ + @Test + public void testPersist() { + Trader trader = new Trader(UUID.randomUUID().hashCode(), new Planet(planetNameGenerator(), 10, 10, + PlanetEvent.SHOP, new ArrayList<Ship>()), new ArrayList<Weapon>(), 0, 0, new ArrayList<Crew>()); + try { + traderDAO.persist(trader); + entityManager.getTransaction().begin(); + Trader trader1 = entityManager.find(Trader.class, trader.getId()); + entityManager.getTransaction().commit(); + Assert.assertEquals(trader1.getId(), trader.getId()); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException(); + } + } + + /** + * Test editing an existing trader in the database + */ + @Test + public void testEdit() { + Trader trader = new Trader(UUID.randomUUID().hashCode(), new Planet(planetNameGenerator(), 10, 10, + PlanetEvent.SHOP, new ArrayList<Ship>()), new ArrayList<Weapon>(), 0, 0, new ArrayList<Crew>()); + try { + traderDAO.persist(trader); + entityManager.getTransaction().begin(); + Trader trader1 = entityManager.find(Trader.class, trader.getId()); + trader1.setFuelStock(10); + traderDAO.update(trader1); + entityManager.getTransaction().commit(); + Assert.assertEquals(trader1.getFuelStock(), 10); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException(); + } + } + + /** + * Test removing an existing trader from the database + */ + @Test + public void testRemove() { + Trader trader = new Trader(UUID.randomUUID().hashCode(), new Planet(planetNameGenerator(), 10, 10, + PlanetEvent.SHOP, new ArrayList<Ship>()), new ArrayList<Weapon>(), 0, 0, new ArrayList<Crew>()); + try { + traderDAO.persist(trader); + traderDAO.remove(trader); + entityManager.getTransaction().begin(); + Trader trader1 = entityManager.find(Trader.class,trader.getId()); + entityManager.getTransaction().commit(); + Assert.assertNull(trader1); + } + catch (Exception e){ + e.printStackTrace(); + throw new IllegalArgumentException(); + } + } + + + /** Random planet name generator + * @return a random planet name */ + private String planetNameGenerator(){ + Random random = new Random(); + String alphabet = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"; + alphabet = alphabet.replace(',',' '); + StringBuilder builder = new StringBuilder(); + for (int i=0;i<100;i++){ + builder.append(alphabet.toCharArray()[random.nextInt(alphabet.length())]); + } + return builder.toString(); + } + +} diff --git a/core/src/main/resources/META-INF/persistence.xml b/core/src/main/resources/META-INF/persistence.xml index 4c58c808..7c239e2d 100644 --- a/core/src/main/resources/META-INF/persistence.xml +++ b/core/src/main/resources/META-INF/persistence.xml @@ -4,8 +4,15 @@ version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="database" transaction-type="RESOURCE_LOCAL"> - <class>com.galaxytrucker.galaxytruckerreloaded.Model.User</class> <class>com.galaxytrucker.galaxytruckerreloaded.Model.Crew.Crew</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.ShipLayout.Room</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.ShipLayout.System</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Map.Trader</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Map.Overworld</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Map.Planet</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Weapons.Weapon</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.Ship</class> + <class>com.galaxytrucker.galaxytruckerreloaded.Model.User</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:h2:./database;DB_CLOSE_ON_EXIT=FALSE;" /> <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" /> diff --git a/exceptions.md b/exceptions.md new file mode 100644 index 00000000..65fc8a09 --- /dev/null +++ b/exceptions.md @@ -0,0 +1,7 @@ +# Persistence: + +### Exception: java.lang.ClassCastException +* stack trace: class org.hibernate.mapping.SingleTableSubclass cannot be cast to class org.hibernate.mapping.RootClass +* Possible Solution: Remove @Id Tags from Subclasses. + +### -- GitLab