I'm learning JPA. In the code below I'm trying to persist Point, then list Points to check and it turns out that it haven't been saved. Why?
Thank you!
PersistenceProvider provider = new PersistenceProvider();
EntityManagerFactory emf = provider.createEntityManagerFactory("sample", null);
EntityManager em = emf.createEntityManager();
// DROP TABLE POINT
// CREATE TABLE POINT (ID BIGINT NOT NULL, X DOUBLE, Y DOUBLE, PRIMARY KEY (ID))
// DELETE FROM SEQUENCE WHERE SEQ_NAME = 'SEQ_GEN'
// SELECT * FROM SEQUENCE WHERE SEQ_NAME = 'SEQ_GEN'
// INSERT INTO SEQUENCE(SEQ_NAME, SEQ_COUNT) values ('SEQ_GEN', 0)
Point p = new Point(1, 1);
em.persist(p);
// UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
// bind => [2 parameters bound]
// SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?
// bind => [1 parameter bound]
em.close();
EntityManager em2 = emf.createEntityManager();
Query query = em2.createQuery("select p from Point p");
List list = query.getResultList();
// SELECT ID, X, Y FROM POINT
System.out.println("Found objects: " + list.size());
// Found objects: 0
for (Object elt: list){
System.out.println(elt);
}
Whole project: https://github.com/greenmarker/EclipseLinkTest
Since you have no transaction there, then nothing is committed.
Some JPA providers will allow "non-transactional" writes (what you're trying to do there, e.g DataNucleus JPA), but many won't, so you need to do
em.getTransaction().begin();
... (persist, merge, remove calls)
em.getTransaction().commit();
if you want vendor-independent persistence code
Related
this is the method Dao layer List,
public List<PortfolioMemberView> getPortfolioMemberViewByPid(Integer pid){
//check the portfolioId value in console
System.out.print(pid);
try {
Session session = sessionFactory.getCurrentSession();
String sql = "from PortfolioMemberView pv where pv.portfolioId = ?0";
Query query = session.createQuery(sql).setParameter(0, pid);
List<PortfolioMemberView> pmvl = query.list();
//check the result list by assetCode in console
for(PortfolioMemberView pv: pmvl){
System.out.print(pv.getAssetCode());
}
return pmvl;
}catch(Exception e){
logger.info("操作失败:" + e.getMessage() + ", " +e.getCause());
throw new RuntimeException();
}
I have a view(That I create) PortfolioMemberView in my database
and it has the following data
inmage
when I involke the method, the console print following result.
2
Hibernate: select portfoliom0_.portfolioId as portfoli1_8_,
portfoliom0_.assetId as assetId2_8_, portfoliom0_.accountType as accountT3_8_, portfoliom0_.assetCode as assetCod4_8_, portfoliom0_.assetLabel as assetLab5_8_, portfoliom0_.value_ as value_6_8_, portfoliom0_.annualReturn as annualRe7_8_, portfoliom0_.returnRate as returnRa8_8_ from PortfolioMemberView portfoliom0_ where portfoliom0_.portfolioId=?
CMPROP0121CMPROP0121CMPROP0121CMPROP0121CMPROP0121
The expected result should be CMPROP0121kckbGYck, because when portfolioId = 2, the assetCode of three object in the resulting list shoud be CMPROP0121,kckb,GYck.
I also copy the query hibenate generated and run it at mysql database, and the result is correct.
Hibernate: select portfoliom0_.portfolioId as portfoli1_8_,
portfoliom0_.assetId as assetId2_8_, portfoliom0_.accountType as accountT3_8_, portfoliom0_.assetCode as assetCod4_8_, portfoliom0_.assetLabel as assetLab5_8_, portfoliom0_.value_ as value_6_8_, portfoliom0_.annualReturn as annualRe7_8_, portfoliom0_.returnRate as returnRa8_8_ from PortfolioMemberView portfoliom0_ where portfoliom0_.portfolioId=?
not sure what's wrong, pls help!!!
I mapped portfolioId as primary Id, and primary Id cannot be duplicated. but obviously the primary key portfolioId is duplicated. I make aother primary key portfolioMemberId, and the problem solved
I am trying to update MySQL table with hibernate. It looks like that it does work, result from hibernate is 1, but table doesn´t change. My code for update :
Session session = GeneralSession.getSession();
session.beginTransaction();
//some code - initialization and logics
//loop
Query updateDuplicity = session .createSQLQuery("UPDATE `t_inzerat` set `actual` = 'D'
WHERE `id` = "+ idSimi);
int resultUpdate = updateDuplicity.executeUpdate();
session.flush();
//end of loop
session.getTransaction().commit();
In console hibernate writes this as:
Hibernate: UPDATE `t_inzerat` set `actual` = 'D' WHERE `id` = 5611
Affected rows : 1
Please what is wrong? Thank you
Have a look hereexample. Do the commit in the tx returned by beginTransaction method
There are the following structure of tables:
CREATE TABLE Train
(
idTrain INT NOT NULL AUTO_INCREMENT,
nameTrain CHAR(20) NOT NULL,
PRIMARY KEY (idTrain)
);
CREATE TABLE Station
(
idStation INT NOT NULL AUTO_INCREMENT,
nameStation CHAR(50) NOT NULL,
PRIMARY KEY (idStation)
);
CREATE TABLE Schedule
(
idStation INT NOT NULL,
idTrain INT NOT NULL,
arrivalTime TIME NOT NULL,
departureTime TIME NOT NULL,
nextStation INT NOT NULL,
kmToNextStation INT NOT NULL,
PRIMARY KEY (idStation, idTrain, nextStation),
FOREIGN KEY (idStation) REFERENCES Station(idStation),
FOREIGN KEY (idTrain) REFERENCES Train(idTrain),
FOREIGN KEY (nextStation) REFERENCES Station(idStation)
);
Necessary to implement the following sql-query using JPA Criteria:
SELECT Station.nameStation, Schedule.arrivalTime, Schedule.departureTime, Schedule.kmToNextStation
FROM Schedule
JOIN Station
ON Station.idStation = Schedule.idStation
JOIN Train
ON Schedule.idTrain = Train.idTrain
WHERE Train.nameTrain = "268A";
Here is my attempt:
EntityManager em = EntitySupport.getEntityManager();
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<ScheduleEntity> cq = builder.createQuery(ScheduleEntity.class);
Root<ScheduleEntity> root = cq.from(ScheduleEntity.class);
Join<ScheduleEntity, TrainEntity> idTrain = root.join("idTrain");
Join<ScheduleEntity, StationEntity> idStation = root.join("idStation");
cq.multiselect(root.get("arrivalTime"),
root.get("departureTime"),
idTrain.get("nameTrain"));
Query query = em.createQuery(cq);
List res = query.getResultList();
System.out.println("Result query: " + res.toString());
Apparently, I'm doing something wrong, because I get the following error:
Exception in thread "main" java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate
appropriate constructor on class [srt.entity.ScheduleEntity]. Expected
arguments are: java.util.Date, java.util.Date, java.lang.String
[select new srt.entity.ScheduleEntity(generatedAlias0.arrivalTime,
generatedAlias0.departureTime, generatedAlias1.nameTrain) from
srt.entity.ScheduleEntity as generatedAlias0 inner join
generatedAlias0.idTrain as generatedAlias1 inner join
generatedAlias0.idStation as generatedAlias2]
Help me make the correct code for the above sql-query using JPA Criteria.
I was wrong in the concept of JPA Criteria. Now I completely understood, the answer would be as follows:
EntityManager em = EntitySupport.getEntityManager();
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<ScheduleEntity> cq = builder.createQuery(ScheduleEntity.class);
Root<ScheduleEntity> from = cq.from(ScheduleEntity.class);
Join<ScheduleEntity, StationEntity> idStation = from.join("idStation");
Join<ScheduleEntity, TrainEntity> idTrain = from.join("idTrain");
Predicate where = builder.equal(idTrain.get("nameTrain"), "268A");
cq.where(where);
List<ScheduleEntity> schedule = em.createQuery(cq).getResultList();
for(ScheduleEntity s : schedule) {
System.out.println(s.toString());
}
The following code:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test.odb");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Point p = new Point(0, 0);
em.persist(p);
em.getTransaction().commit();
em.getTransaction().begin();
Query query = em.createQuery("UPDATE Point SET x = 1001 where x = 0");
int updateCount = query.executeUpdate();
em.getTransaction().commit();
TypedQuery<Point> myquery = em.createQuery("SELECT p from Point p where p.x = 1001", Point.class);
List<Point> results = myquery.getResultList();
System.out.println("X coordinate is: " + results.get(0).getX());
em.close();
prints out: X coordinate is: 0
which is wrong because X coordinate should be 1001
But if I change the code to:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test.odb");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Point p = new Point(0, 0);
em.persist(p);
em.getTransaction().commit();
em.getTransaction().begin();
Query query = em.createQuery("UPDATE Point SET x = 1001 where x = 0");
int updateCount = query.executeUpdate();
em.getTransaction().commit();
em.close();
em = emf.createEntityManager();
TypedQuery<Point> myquery = em.createQuery("SELECT p from Point p where p.x = 1001", Point.class);
List<Point> results = myquery.getResultList();
System.out.println("X coordinate is: " + results.get(0).getX());
em.close();
The result is same as expected:
X coordiate is: 1001
What have I done wrong in the first code snippet?
UPDATE queries bypass the EntityManager, which means that the EntityManager may not have an up to date view of the real objects in the database.
As explained in the UPDATE queries page in the ObjectDB Manual:
"Updating entity objects in the database using an UPDATE query may be slightly more efficient than retrieving entity objects and then updating them, but it should be used cautiously because bypassing the EntityManager may break its synchronization with the database. For example, the EntityManager may not be aware that a cached entity object in its persistence context has been modified by an UPDATE query. Therefore, it is a good practice to use a separate EntityManager for UPDATE queries."
Using a separate EntityManager is exactly what you did by closing and opening a new EntityManager in your revised code.
Alternatively, if you want to use the same EntityManager, you may clear its persistence context (i.e. its cache), after running the UPDATE query and before running the SELECT query.
I am trying to retrieve data from a table which has a foreign key, "reg_no". And the foreign key is not unique, it can be duplicated.
Now I want to retrieve the data from this table using this foreign key. I will provide a "reg_no" and the Java Persistence API will retrieve a list of the result set from the table wrt to "reg_no" provided.
Please enlighten me how can I solve this problem?
You can do something like this, using JPQL:
String queryString = "SELECT t FROM YourTable t " +
"WHERE reg_no = :regNo";
Query query = getEntityManager().createQuery(queryString);
query.setParameter("regNo", regNoValue);
return query.getResultList();
EntityManager entityManager = entityManagerFactory.createEntityManager();
List results = em.createQuery("SELECT c FROM Vehicle v WHERE reg_no = :reg_no").setParameter("reg_no", new String("0000")).getResultList;