My problem is when I save a person domiciled the id of the person record is 1 and the address 2 and when I save another record the id of person is 3 and the domicile 4 and so is increased, I want to increase as it should be is to record who is 1 and for of registered prox 1 for registration is 2 and 2 the next 3 and 3 and so on.
Then I leave the source code of the entities, the main, the method to keep and what gives me the console when I create the tables. I'm using netbeans 7.4 and EclipseLink library jpa2.1 and jdbc for sqlite dirver
#Entity
public class Persona implements Serializable {
protected static final long serialVersionUID = 1L;
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private Long id;
private String nombre;
#OneToOne (cascade = CascadeType.ALL)
private Domicilio domicilio;
public Persona() {
}
public Persona(String nombre) {
this.nombre = nombre;
domicilio= new Domicilio();
}
public Domicilio getDomicilio() {
return domicilio;
}
public void setDomicilio(Domicilio domicilio) {
this.domicilio = domicilio;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
Entity Domicilio:
#Entity
public class Domicilio implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String calle;
public Domicilio() {
}
public Domicilio(String calle) {
this.calle = calle;
}
public String getCalle() {
return calle;
}
public void setCalle(String calle) {
this.calle = calle;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
Method found in the class PersonaJpaController used to save the record
public void guardar(){
persona= new Persona("angel");
persona.getDomicilio().setCalle("alpatacal");
create(persona);
}
This is my main program
public class Pruebaentidades {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pruebaentidadesPU");
EntityManager em = emf.createEntityManager();// create tables
PersonaJpaController p= new PersonaJpaController(Persistence.createEntityManagerFactory("pruebaentidadesPU"));
p.guardar();
}
}
This is what gives me the console when I create tables
[EL Info]: 2014-01-03 17:27:01.189--ServerSession(24979675)--EclipseLink, version: Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5
[EL Info]: connection: 2014-01-03 17:27:01.379--Not able to detect platform for vendor name [SQLite3]. Defaulting to [org.eclipse.persistence.platform.database.DatabasePlatform]. The database dialect used may not match with the database you are using. Please explicitly provide a platform using property eclipselink.platform.class.name.
[EL Info]: connection: 2014-01-03 17:27:01.446--ServerSession(24979675)--file:/C:/Users/VM/Desktop/Mis Proyectos/Proyectos Netbeans/pruebaentidades/build/classes/_pruebaentidadesPU login successful
[EL Warning]: 2014-01-03 17:27:01.6--ServerSession(24979675)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: near "CONSTRAINT": syntax error
Error Code: 0
Call: ALTER TABLE PERSONA ADD CONSTRAINT FK_PERSONA_DOMICILIO_ID FOREIGN KEY (DOMICILIO_ID) REFERENCES DOMICILIO (ID)
Query: DataModifyQuery(sql="ALTER TABLE PERSONA ADD CONSTRAINT FK_PERSONA_DOMICILIO_ID FOREIGN KEY (DOMICILIO_ID) REFERENCES DOMICILIO (ID)")
for those who have this same problem I want to say that the solution to the problem was to create a sequence for each table and use the strategy generation secuence.
add these statements for each entity allowing me to create a sequence for each table
Entity Persona:
#GeneratedValue (strategy = GenerationType.SEQUENCE, generator = "PERS_SEQ")
#SequenceGenerator ( name = "PERS_SEQ" , sequenceName = "PERS_SEQ")
Entity Domicilio:
#GeneratedValue(strategy = GenerationType.SEQUENCE , generator = "DOM_SEQ")
#SequenceGenerator ( name = "DOM_SEQ" , sequenceName = "DOM_SEQ")
Related
I am having a JPQL query which has to fetch only two fields one integer and a list value. Here I had created a Dto and mentioned the fields that need to be fetched.
//all variables are defined
query = new StringBuilder();
query.append(ReposJPQL.GET_INCIDENTS);
q = em.createQuery(query.toString());
result = q.getResultList();
where query,
GET_INCIDENTS = "SELECT DISTINCT searchDto ("
+ "ih.Id, ih.logs )"
+ "FROM Hdr ih left join ih.logs sl";
searchDto
public class SearchDto implements Serializable {
private static final long serialVersionUID = 1L;
private Integer ID
private List<IncidentStatusLogDto> statusLogs;
public SearchDto () {
}
public SearchDto (Long incidentId, List<IncidentStatusLogDto> statusLogs) {
super();
this.incidentId = incidentId;
this.statusLogs = statusLogs;
}
}
HDR Entity
#Entity
#Table(name="TB_HDR")
public class IncidentHdr implements Serializable {
private static final long serialVersionUID = 1L;
private Id;
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, fetch = FetchType.LAZY, mappedBy="incidentHdr")
#JsonManagedReference
private List<Log> logs;
//getters and setters
}
Here I had added the constructor in searchDto as required, still it throws exception.
no appropriate constructor in class: SearchDto]
org.hibernate.hql.internal.ast.DetailedSemanticException: Unable to locate appropriate constructor on class SearchDto]. Expected arguments are: long, java.util.Collection
When I tried with only Id as value and removed the list it working.
You have a couple of errors in the SearchDTO class:
Missing a semicolon in private Integer ID should be private Integer ID;
You are trying to set this.incidentId = incidentId; in the constructor but you don't have defined the variable.
As I don't know if you have missed it or if you want to replace it by the variable ID my proposal of solution is:
public class SearchDto implements Serializable {
private static final long serialVersionUID = 1L;
private Integer ID;
private Long incidentId;
private List<IncidentStatusLogDto> statusLogs;
public SearchDto () {
}
public SearchDto (Long incidentId, List<IncidentStatusLogDto> statusLogs) {
super();
this.incidentId = incidentId;
this.statusLogs = statusLogs;
}
}
I am trying to lazily fetch PetDetails entity using JPA. However, I get LazyInitialization Exception. I read many solutions for this exception and came to find solution using JOIN FETCH in JPQL. Also people recommended using Criteria queries. However, I am trying to look for a solution if there is a way I can fetch the PetDetails entity the way I want without using queries directly or depending on Criteria API or without using EAGER FETCH. I might be missing something. I would appreciate for any help or suggestion. Below are the code samples:
1. Controller class:
#Controller
public class PetController {
private static Logger LOGGER = Logger.getLogger(PetController.class);
#Autowired
private PetService petService;
#RequestMapping(value = "/", method = RequestMethod.GET)
public void manageAndDisplayPet() {
PetDetails petDetails = new PetDetails();
petDetails.setName("DOG");
Pet pet = new Pet(petDetails);
// save
petService.savePet(pet);
// retrieve
LOGGER.debug("**********************" + petService.getPet());
LOGGER.debug("**********************" + pet.getPetDetails());
}
}
2. PetService class:
#Service
public class PetService {
#Autowired
private PetDAO petDAO;
#Transactional
public void savePet(Pet pet) {
petDAO.savePet(pet);
}
#Transactional
public Pet getPet() {
return petDAO.getPet();
}
}
3. PetDAO class
#Repository
#EnableTransactionManagement
public class PetDAO {
#PersistenceContext(unitName = "petcontext")
private EntityManager entityManagerFactory;
public void savePet(Pet pet) {
entityManagerFactory.persist(pet);
}
public Pet getPet() {
Pet pet = (Pet) entityManagerFactory.find(Pet.class, 1);
return pet;
}
}
4. Pet Entity:
#Entity
#Table(name = "t_pet")
public class Pet {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#JoinColumn(name = "pet_details")
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private PetDetails petDetails;
public Pet() {
}
public Pet(PetDetails petDetails) {
this.petDetails = petDetails;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public PetDetails getPetDetails() {
return petDetails;
}
public void setPetDetails(PetDetails petDetails) {
this.petDetails = petDetails;
}
#Override
public String toString() {
return "Pet [id=" + id + ", petDetails=" + petDetails + "]";
}
}
5. PetDetails Entity:
#Entity
#Table(name = "pet_details")
public class PetDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "pet_name")
private String name;
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;
}
#Override
public String toString() {
return "PetDetails [id=" + id + ", name=" + name + "]";
}
}
Thank you for your help.
Easy thing you can do is to call pet.getPetDetails() inside PetService#getPet. This solution is not very clear, but it will force JPA to fetch entity too. This is solution for your question, but not the good way anyways.
What is the good way?
The good way may depend on your particular usecase:
If you need this details everytime — you should use EAGER_FETCH
If you need it time to time than good solution it to use JPQL with JOIN FETCH
But the best way is to select not entites, but DTOs, which will contain whole information which your application needs and not more. It may be achieved with SELECT NEW expression as described here
I have simple webapp in spring 3, jpa, eclipse link, spring data. When I try run it (on VMware server) I have got error:
org.springframework.data.mapping.PropertyReferenceException: No property show found for type foo.domain.Catalog
Entity:
#Entity
#Table(name="catalog")
#NamedQuery(name="Catalog.findAll", query="SELECT c FROM Catalog c")
public class Catalog implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private String id;
private String adres;
private String opis;
private String tytul;
//bi-directional many-to-one association to Category
#ManyToOne
#JoinColumn(name="cname", referencedColumnName="name")
private Category category;
public Catalog() {
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getAdres() {
return this.adres;
}
public void setAdres(String adres) {
this.adres = adres;
}
public String getOpis() {
return this.opis;
}
public void setOpis(String opis) {
this.opis = opis;
}
public String getTytul() {
return this.tytul;
}
public void setTytul(String tytul) {
this.tytul = tytul;
}
public Category getCategory() {
return this.category;
}
public void setCategory(Category category) {
this.category = category;
}
Interface repository:
public interface KatalogRepository extends JpaRepository<Catalog, Long>{
#Query("select c from Catalog c left join fetch c.name")
public List<Catalog> showAll();
#Query("select c from Catalog c where c.tytul like %?1")
public Catalog findByTytul(String tytul);
#Query("select c from Category c")
public List<Category> showAllCategory();
#Query("select c from Category c where c.id =:id")
public Category findCategoryById(Long id);
}
I tried many solutions but didn't help. Has someone got the similar problem? Thanks for help.
My dao class:
#Repository
public class KatalogDAO {
#Autowired
KatalogRepository katalogRepository;
//#Autowired
//CategoryRepository categoryRepository;
#Transactional
public List<Catalog> showAllSites(){
return katalogRepository.showAll();
}
#Transactional
public void saveSite(Catalog catalog){
katalogRepository.saveAndFlush(catalog);
}
#Transactional
public Catalog showByTitle(String tytul){
return katalogRepository.findByTytul(tytul);
}
#Transactional
public List<Category> showAllCategory(){
return katalogRepository.showAllCategory();
}
#Transactional
public Category findCategoryById(Long id){
return katalogRepository.findCategoryById(id);
}
}
And endpoint:
#Component
public class CatalogEndpoint {
#Autowired
KatalogDAO katalogDAO;
public List<Catalog> showAllSites(){
return katalogDAO.showAllSites();
}
public void saveSite(Catalog catalog ){
katalogDAO.saveSite(catalog);
}
public Catalog getByTitle(String tytul){
return katalogDAO.showByTitle(tytul);
}
public List<Category> showCategory(){
return katalogDAO.showAllCategory();
}
public Category findCategoryById(Long id){
return katalogDAO.findCategoryById(id);
}
}
I think the problem is that you wrote this query :
#Query("select c from Category c")
Which should be :
#Query("select * from Category c")
The error is probably caused by the Spring Data JPA framework, because if you give it a wrong request, it will probably try to generate a request based on the method name, but in this case, your method name should be "findAll". Moreover, the findAll() method is already given by the Spring Data JPA framework thanks to the CRUDRepository interface.
I am trying to store some custom object as a blob in SqlLite db. The object is a field of a class extending Model. All other fields (of primitive types) go successfully in the DB, but the custom one - it is null always.
#Table(name = "data")
public class Data extends Model {
#Column(name = "number")
private int number;
#Column(name = "blob")
private Contact blob;
...
This is how i store the entity
Data data = new Data(0, new Contact(id, name, number));
data.save();
Here is the contact class
public class Contact {
private String id;
private String name;
private String number;
...
I believe a TypeSerializer is needed, so I've created one.
public class ContactSerializer extends TypeSerializer {
private static final String ELEMENTS_DELIMITER = ";";
#Override
public Object deserialize(Object asString) {
String[] afterSplit = ((String) asString).split(ELEMENTS_DELIMITER);
return new Contact(afterSplit[0], afterSplit[1], afterSplit[2]);
}
#Override
public Class<?> getDeserializedType() {
return Contact.class;
}
#Override
public SerializedType getSerializedType() {
return SerializedType.STRING;
}
#Override
public Object serialize(Object asContact) {
Contact temp = (Contact) asContact;
return temp.getId() + ELEMENTS_DELIMITER + temp.getName() + ELEMENTS_DELIMITER
+ temp.getNumber();
}
}
When i query the db I got object with this particular field "Contact" as null always. Where might be the problem? Do I need to specify which is the TypeSerializer for my object? Or the implementation of TypeSerializer I've created is wrong?
You also need to extent Contact from Model:
#Table(name = "contact")
public class Contact extends Model{
#Column(name = "id")
private String id;
#Column(name = "name")
private String name;
#Column(name = "number")
private String number;
}
Now everything should work out of the box. It's a bit late for a response but perhaps I will help someone else.
I have following class as superclass
#Entity
#MappedSuperclass
public class Location implements LocationCapable {
#Basic
private Double latitude;
#Basic
private Double longitude;
#Basic
private List<String> geocells;
#PrePersist
#Transient
private void generateGeoCells() {
geocells = GeocellManager.generateGeoCell(getLocation());
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
#Override
#Transient
#JsonIgnore
public Point getLocation() {
return new Point(latitude, longitude);
}
#Override
#Transient
#JsonIgnore
public String getKeyString() {
return latitude + ":" + longitude;
}
#Override
public List<String> getGeocells() {
return geocells;
}
public void setGeocells(List<String> geocells) {
this.geocells = geocells;
}
}
And another one which inherits from this
But when I try to run JUnit test I got this
Caused by: org.datanucleus.metadata.InvalidMetaDataException: Class Location has application-identity and no objectid-class specified yet has 0 primary key fields. Unable to use SingleFieldIdentity.
at org.datanucleus.metadata.AbstractClassMetaData.determineObjectIdClass(AbstractClassMetaData.java:1032)
at org.datanucleus.metadata.ClassMetaData.populate(ClassMetaData.java:205)
at org.datanucleus.metadata.AbstractClassMetaData.validateSuperClass(AbstractClassMetaData.java:720)
at org.datanucleus.metadata.AbstractClassMetaData.determineSuperClassName(AbstractClassMetaData.java:642)
at org.datanucleus.metadata.ClassMetaData.populate(ClassMetaData.java:193)
at org.datanucleus.metadata.MetaDataManager$1.run(MetaDataManager.java:2317)
at java.security.AccessController.doPrivileged(Native Method)
at org.datanucleus.metadata.MetaDataManager.populateAbstractClassMetaData(MetaDataManager.java:2311)
at org.datanucleus.metadata.MetaDataManager.populateFileMetaData(MetaDataManager.java:2148)
at org.datanucleus.metadata.MetaDataManager.initialiseFileMetaDataForUse(MetaDataManager.java:864)
at org.datanucleus.metadata.MetaDataManager.loadPersistenceUnit(MetaDataManager.java:794)
at org.datanucleus.jpa.EntityManagerFactoryImpl.initialisePMF(EntityManagerFactoryImpl.java:488)
at org.datanucleus.jpa.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:355)
at org.datanucleus.store.appengine.jpa.DatastoreEntityManagerFactory.<init>(DatastoreEntityManagerFactory.java:63)
at org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider.createEntityManagerFactory(DatastorePersistenceProvider.java:35)
at javax.persistence.Persistence.createFactory(Persistence.java:172)
... 67 more
Also I've tried to add in supperclass the key field annotated with #Id but it gives no result for me
You have to have an #Id field, as the message says.
Looks like it was some problem with enhancing or eclipse plugin, no metter after restart of IDE the problem dessapiared. But only this problem with ID. Actually I've faced with another very strange problem related to embedded entities. I have following domain model:
#Entity
public class City {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key id;
#Basic
private String name;
// Entity won't persist if location is not null, requires to persist with
// further update
#Embedded
// #OneToOne(cascade = CascadeType.ALL) it works the same when I add or remove this line
private Location location;
/* getters and setters */
}
#Embeddable
public class Location implements LocationCapable {
#Basic
#NotNull
private Double latitude;
#Basic
#NotNull
private Double longitude;
#Basic
private List<String> geocells;
/* getters and setters */
}
To test it I have following JUnit test case:
#Test
public void testSave() throws Exception {
City city = new City("testCity1", new Location(1d, 1d));
cityDao.persist(city);
assertNotNull(city.getId());
}
cityDao.persist(city) does simply jpaTemplate.persist(object);
And at when I try to persist this entity I got following exception:
Caused by: java.lang.IllegalArgumentException: out of field index :-1
at com.myproject.model.Location.jdoProvideField(Location.java)
at org.datanucleus.state.JDOStateManagerImpl.provideField(JDOStateManagerImpl.java:2585)
at org.datanucleus.state.JDOStateManagerImpl.provideField(JDOStateManagerImpl.java:2555)
at org.datanucleus.store.mapped.mapping.CollectionMapping.postInsert(CollectionMapping.java:91)
at org.datanucleus.store.mapped.mapping.EmbeddedPCMapping.postInsert(EmbeddedPCMapping.java:104)
at org.datanucleus.store.appengine.DatastoreRelationFieldManager.runPostInsertMappingCallbacks(DatastoreRelationFieldManager.java:217)
at org.datanucleus.store.appengine.DatastoreRelationFieldManager.access$200(DatastoreRelationFieldManager.java:48)
at org.datanucleus.store.appengine.DatastoreRelationFieldManager$1.apply(DatastoreRelationFieldManager.java:116)
at org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelations(DatastoreRelationFieldManager.java:81)
at org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations(DatastoreFieldManager.java:955)
at org.datanucleus.store.appengine.DatastorePersistenceHandler.storeRelations(DatastorePersistenceHandler.java:546)
at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPostProcess(DatastorePersistenceHandler.java:304)
at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects(DatastorePersistenceHandler.java:256)
at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:240)
at org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent(JDOStateManagerImpl.java:3185)
at org.datanucleus.state.JDOStateManagerImpl.flush(JDOStateManagerImpl.java:4513)
at org.datanucleus.ObjectManagerImpl.flushInternal(ObjectManagerImpl.java:2814)
at org.datanucleus.ObjectManagerImpl.flush(ObjectManagerImpl.java:2754)
at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:2893)
at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:369)
at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:256)
at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:104)
at org.datanucleus.store.appengine.jpa.DatastoreEntityTransactionImpl.commit(DatastoreEntityTransactionImpl.java:55)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
... 41 more