I would like to request please help me to find out solution for updating the foreign key value in other table.
for example:-
If we taken Device Table
columns are :- devicename
deviceId
displayname
userId
roomId
isDeleted
other table is Rooms Table
columns are :- roomName
roomId
roomType
isDeleted
Hear it is looking like one-to-many relationship.
i.e., one room will contain many devices.
In the above two tables roomId is primary key in Rooms Table and roomId is forgin key in Device Table.
So, Hear what we want is we have to update the roomId in DeviceTable.
I tried but, I cant able to find the solution for this, I request you guys' please help me for this solution.
the database tables will be like
Room Table(room_table)
room_id room_name room_type
1 ROOM1 ROOM_TYPE1
2 ROOM2 ROOM_TYPE2
Device Table like(device_table)
device_id device_name display_name room_id
1 DEVICE1 DISPLAY1 1
2 DEVICE2 DISPLAY2 2
I hope you guys understand the above tables.
So, now Coming to my required task is:-
I want to update roomId in device table i.e., for DEVICE2 we have to update from roomId 1 to roomId 2 AS SHOWN IN BELOW.
Device Table like(device_table)
device_id device_name display_name room_id
1 DEVICE1 DISPLAY1 1
2 DEVICE2 DISPLAY2 2
for this I wrote java code like:-
#Entity
#Table(name = "device_table")
public class Device {
#Id
#Column(name = "device_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int deviceId;
#Column(name = "device_name")
private String deviceName;
#Column(name = "display_name")
private String dispalyName;
#ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
//private List<Room> roomList = new ArrayList<>();
#JoinColumn(name = "ROOM_ID")
private Room roomList;
//setters & getters
}
#Entity
#Table(name = "room_table")
public class Room {
#Id
#Column(name = "room_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int roomId;
#Column(name = "room_name")
private String roomName;
#Column(name = "room_type")
private String roomType;
#OneToMany(mappedBy="roomList")
private Collection<Device> deviceList = new ArrayList<>();
//setters & getters
}
For updating I tried code like below.
public class SaveDataClientTest {
public static void main(String[] args) {
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
session.beginTransaction();
CriteriaBuilder userBuilder = session.getCriteriaBuilder();
CriteriaUpdate<Device> deviceUpdate = userBuilder.createCriteriaUpdate(Device.class);
Root<Device> deviceUpdateRoot = deviceUpdate.from(Device.class);
Subquery<Device> deviceSubquery = deviceUpdate.subquery(Device.class);
Root<Device> roomRoot = deviceSubquery.from(Device.class);
Join<Device, Room> join = roomRoot.join("roomList", JoinType.LEFT);
deviceUpdate.set(deviceUpdateRoot.get("dispalyName"), "DISPLAY12345");
deviceUpdate.set(join.get("roomId"), 2);
deviceUpdate.where(userBuilder.equal(deviceUpdateRoot.get("deviceName"), "DEVICE2"));
int returnValue = session.createQuery(deviceUpdate).executeUpdate();
System.out.println(returnValue);
session.getTransaction().commit();
} catch (HibernateException e) {
e.printStackTrace();
}
}
}
I am getting error like
Oct 01, 2020 8:00:03 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Oct 01, 2020 8:00:03 PM org.hibernate.hql.internal.ast.ErrorCounter reportError
ERROR: Invalid path: 'generatedAlias1.roomId'
Oct 01, 2020 8:00:03 PM org.hibernate.hql.internal.ast.ErrorCounter reportError
ERROR: Invalid path: 'generatedAlias1.roomId'
Invalid path: 'generatedAlias1.roomId'
at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)
at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:214)
at org.hibernate.hql.internal.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:1038)
at org.hibernate.hql.internal.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:1026)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.assignment(HqlSqlBaseWalker.java:1054)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.setClause(HqlSqlBaseWalker.java:765)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.updateStatement(HqlSqlBaseWalker.java:381)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:269)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:266)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:553)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:662)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3324)
at org.hibernate.query.criteria.internal.AbstractManipulationCriteriaQuery$1.buildCompiledQuery(AbstractManipulationCriteriaQuery.java:112)
at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3628)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:203)
at com.infotech.client.SaveDataClientTest.main(SaveDataClientTest.java:54)
Exception in thread "main" java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.roomId' [update com.infotech.entities.Device as generatedAlias0 set generatedAlias0.dispalyName = :param0, generatedAlias1.roomId = 2 where generatedAlias0.deviceName=:param1]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:133)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:670)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3324)
at org.hibernate.query.criteria.internal.AbstractManipulationCriteriaQuery$1.buildCompiledQuery(AbstractManipulationCriteriaQuery.java:112)
at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3628)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:203)
at com.infotech.client.SaveDataClientTest.main(SaveDataClientTest.java:54)
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.roomId' [update com.infotech.entities.Device as generatedAlias0 set generatedAlias0.dispalyName = :param0, generatedAlias1.roomId = 2 where generatedAlias0.deviceName=:param1]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:272)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:553)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:662)
... 6 more
will you please help me to solve this issue.
Thanks.
Have you tried the following?
CriteriaUpdate<Device> deviceUpdate = userBuilder.createCriteriaUpdate(Device.class);
Root<Device> deviceUpdateRoot = deviceUpdate.from(Device.class);
deviceUpdate.set(deviceUpdateRoot.get("dispalyName"), "DISPLAY12345");
deviceUpdate.set(deviceUpdateRoot.get("roomList").get("roomId"), 2);
deviceUpdate.where(userBuilder.equal(deviceUpdateRoot.get("deviceName"), "DEVICE2"));
int returnValue = session.createQuery(deviceUpdate).executeUpdate();
or this?
CriteriaUpdate<Device> deviceUpdate = userBuilder.createCriteriaUpdate(Device.class);
Root<Device> deviceUpdateRoot = deviceUpdate.from(Device.class);
deviceUpdate.set(deviceUpdateRoot.get("dispalyName"), "DISPLAY12345");
deviceUpdate.set(deviceUpdateRoot.get("roomList"), session.getReference(Room.class, 2));
deviceUpdate.where(userBuilder.equal(deviceUpdateRoot.get("deviceName"), "DEVICE2"));
int returnValue = session.createQuery(deviceUpdate).executeUpdate();
Related
I'm currently working on an application wherein I'm trying to access a local MySQL database, and specifically trying to run the code:
DataManagerImpl dm = new DataManagerImpl();
System.out.println(dm.findJobByCode("ABN54"));
As a basic check to see if I can actually query the database.
This is the start of the OrderTable entity class:
#Entity
#Table(name = "order_table")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "OrderTable.findAll", query = "SELECT o FROM OrderTable o")
, #NamedQuery(name = "OrderTable.findByOrderID", query = "SELECT o FROM OrderTable o WHERE o.orderID = :orderID")
, #NamedQuery(name = "OrderTable.findByTotalPrice", query = "SELECT o FROM OrderTable o WHERE o.totalPrice = :totalPrice")
, #NamedQuery(name = "OrderTable.findBySpecialInstructions", query = "SELECT o FROM OrderTable o WHERE o.specialInstructions = :specialInstructions")
, #NamedQuery(name = "OrderTable.findByStatus", query = "SELECT o FROM OrderTable o WHERE o.status = :status")
, #NamedQuery(name = "OrderTable.findByPaymentdetailID", query = "SELECT o FROM OrderTable o WHERE o.paymentdetailID = :paymentdetailID")
, #NamedQuery(name = "OrderTable.findByDateSubmitted", query = "SELECT o FROM OrderTable o WHERE o.dateSubmitted = :dateSubmitted")})
public class OrderTable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "orderID")
private Integer orderID;
#Column(name = "total_price")
private Float totalPrice;
#Column(name = "special_instructions")
private String specialInstructions;
#Column(name = "status")
private String status;
#Column(name = "payment_detailID")
private String paymentdetailID;
#Column(name = "date_submitted")
#Temporal(TemporalType.DATE)
private Date dateSubmitted;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "orderTable")
private PaymentDetail paymentDetail;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "orderID")
private Collection<Job> jobCollection;
#JoinColumn(name = "account_no", referencedColumnName = "account_no")
#ManyToOne
private Customer accountNo;
And here is the start of my Job class:
#Entity
#Table(name = "job")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Job.findAll", query = "SELECT j FROM Job j")
, #NamedQuery(name = "Job.findByCode", query = "SELECT j FROM Job j WHERE j.code = :code")
, #NamedQuery(name = "Job.findByJobDescription", query = "SELECT j FROM Job j WHERE j.jobDescription = :jobDescription")
, #NamedQuery(name = "Job.findByPrice", query = "SELECT j FROM Job j WHERE j.price = :price")
, #NamedQuery(name = "Job.findByJobDeadline", query = "SELECT j FROM Job j WHERE j.jobDeadline = :jobDeadline")
, #NamedQuery(name = "Job.findByOrderID", query = "SELECT j FROM Job j WHERE j.orderID = :orderID")})
public class Job implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "code")
private String code;
#Column(name = "job_description")
private String jobDescription;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "price")
private Float price;
#Column(name = "job_deadline")
#Temporal(TemporalType.DATE)
private Date jobDeadline;
#JoinColumn(name = "orderID", referencedColumnName = "orderID")
#ManyToOne(optional = false)
private OrderTable orderID;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "code")
private Collection<JobLine> jobLineCollection;
Here is the error I'm getting from running this.
[EL Info]: 2018-03-28 15:40:58.826--ServerSession(1692092775)--EclipseLink,
version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
[EL Info]: connection: 2018-03-28 15:40:59.062--ServerSession(1692092775)--file:/E:/Documents/GitHub/Bapers/build/classes/_BapersPU login successful
[EL Warning]: 2018-03-28 15:40:59.139--ServerSession(1692092775)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Exception in thread "main" javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'payment_detailID' in 'field list'
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'payment_detailID' in 'field list'
Error Code: 1054
Call: SELECT orderID, date_submitted, payment_detailID, special_instructions, status, total_price, account_no FROM order_table WHERE (orderID = ?)
Error Code: 1054
bind => [1 parameter bound]
Query: ReadObjectQuery(name="orderID" referenceClass=OrderTable )
Call: SELECT orderID, date_submitted, payment_detailID, special_instructions, status, total_price, account_no FROM order_table WHERE (orderID = ?)
bind => [1 parameter bound]
Query: ReadObjectQuery(name="orderID" referenceClass=OrderTable )
at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:378)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260)
at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:517)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:400)
at data.DataManagerImpl.findJobByCode(DataManagerImpl.java:127)
at solsoftbapers2.SolSoftBapers2.main(SolSoftBapers2.java:35)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'payment_detailID' in 'field list'
Error Code: 1054
Call: SELECT orderID, date_submitted, payment_detailID, special_instructions, status, total_price, account_no FROM order_table WHERE (orderID = ?)
bind => [1 parameter bound]
Query: ReadObjectQuery(name="orderID" referenceClass=OrderTable )
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:682)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2002)
at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectOneRow(DatasourceCallQueryMechanism.java:714)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectOneRowFromTable(ExpressionQueryMechanism.java:2801)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectOneRow(ExpressionQueryMechanism.java:2754)
at org.eclipse.persistence.queries.ReadObjectQuery.executeObjectLevelReadQuery(ReadObjectQuery.java:545)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1168)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127)
at org.eclipse.persistence.queries.ReadObjectQuery.execute(ReadObjectQuery.java:431)
at org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:3214)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.indirection.NoIndirectionPolicy.valueFromQuery(NoIndirectionPolicy.java:326)
at org.eclipse.persistence.mappings.ForeignReferenceMapping.valueFromRowInternal(ForeignReferenceMapping.java:2294)
at org.eclipse.persistence.mappings.OneToOneMapping.valueFromRowInternal(OneToOneMapping.java:1860)
at org.eclipse.persistence.mappings.ForeignReferenceMapping.valueFromRow(ForeignReferenceMapping.java:2144)
at org.eclipse.persistence.mappings.ForeignReferenceMapping.readFromRowIntoObject(ForeignReferenceMapping.java:1471)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildAttributesIntoObject(ObjectBuilder.java:461)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:1004)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneNormally(ObjectBuilder.java:898)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:851)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:734)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:688)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.buildObject(ObjectLevelReadQuery.java:795)
at org.eclipse.persistence.queries.ReadObjectQuery.registerResultInUnitOfWork(ReadObjectQuery.java:885)
at org.eclipse.persistence.queries.ReadObjectQuery.executeObjectLevelReadQuery(ReadObjectQuery.java:552)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1168)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127)
at org.eclipse.persistence.queries.ReadObjectQuery.execute(ReadObjectQuery.java:431)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1215)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1751)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258)
... 4 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'payment_detailID' in 'field list'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
at com.mysql.jdbc.Util.getInstance(Util.java:383)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1062)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4208)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4140)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2597)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2758)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2826)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2212)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1007)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:642)
... 44 more
C:\Users\Daniel\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 1 second)
I'm fairly new to using JPA and databases in Java applications, so I imagine I've made a few small mistakes which are the problem? Any help would be greatly appreciated.
I removed the payment_detailID query as well as annotations and variable declerations related to it, which seemed to fix the issue (payment_detailID wasn't in the OrderTable as a column in the database).
I then found I was getting another error which seemed to be related to how JPA was building SQL statements and that one of my columns was "City/Town". For some reason it really didn't like the "/" being there.
So I renamed the column "city" and now it's working fine.
i have a class:
#Entity
#Table(name = "days")
public class DayEntry {
#Expose
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
.
.
#Expose
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "day_item_hours")
#MapKeyJoinColumn(name = "item_id")
#Column(name = "hours")
private Map<Item, Double> itemsHours;
.
.
}
I need to get from DB all DayEntries which contain specific Item in itemHours field.
I tried:
private final String FIND_BY_ACTIVITY = "from DayEntry d where :activity in index(d.itemsHours)";
#Override
public Collection<DayEntry> findByActivity(Item activity) {
Query query = entityManager.createQuery(FIND_BY_ACTIVITY);
query.setParameter("activity", activity);
return query.getResultList();
}
And get this:
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 75 [from ua.siemens.dbtool.model.timesheet.DayEntry d where :activity in index(d.itemsHours)]] with root cause
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 75 [from ua.siemens.dbtool.model.timesheet.DayEntry d where :activity in index(d.itemsHours)]
Not sure how to handle this.
Thanks!
UPDATE
For the moment i ended up with plain SQL Query:
private final String FIND_BY_ACTIVITY = "SELECT * FROM days where id = (SELECT DayEntry_id from day_item_hours where day_item_hours.item_id = :activityId)";
#Override
public Collection<DayEntry> findByActivity(Item activity) {
Query query = entityManager.createNativeQuery(FIND_BY_ACTIVITY_ID, DayEntry.class);
query.setParameter("activityId", activity.getId());
return query.getResultList();
}
but still i wonder how to do it with HQL.
I'm constantly getting error when i wanna insert some data
Project Class
#Entity
#NamedQueries({
#NamedQuery(name = "Project.findAll",
query = "SELECT p FROM Project p"),
#NamedQuery(name = "Project.findByTitle",
query = "SELECT p FROM Project p WHERE p.title = :title")
})
public class Project implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int projectId;
#Column
private String title;
#Column
private String description;
#Column
private Date projectDate;
#ManyToOne
#JoinColumn(name = "projectStatusId")
private ProjectStatus projectStatus;
#OneToMany(mappedBy = "projectMemberId",fetch = FetchType.EAGER)
private List<ProjectMember> memberList = new ArrayList<ProjectMember>();
/**
* Setters and Getters
*/
}
ProjectMember Class
#Entity
#NamedQueries({
#NamedQuery(name = "ProjectMember.findAll",
query = "SELECT pm FROM ProjectMember pm"),
#NamedQuery(name = "ProjectMember.findByProject",
query = "SELECT pm FROM ProjectMember pm WHERE pm.project = :project"),
#NamedQuery(name = "ProjectMember.findByUser",
query = "SELECT pm FROM ProjectMember pm WHERE pm.user = :user"),
#NamedQuery(name = "ProjectMEmeber.findByUserAndProject",
query = "SELECT pm FROM ProjectMember pm WHERE pm.user = :user AND pm.project = :project")
})
public class ProjectMember implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int projectMemberId;
#Column
private Date activationDate;
#Column
private Date lastActiveDate;
#ManyToOne
#JoinColumn(name = "memberStatusId")
private MemberStatus memberStatus;
#ManyToOne
#JoinColumn(name = "projectId")
private Project project;
#ManyToOne
#JoinColumn(name = "memberRoleId")
private MemberRole memberRole;
#ManyToOne
#JoinColumn(name = "userId")
private User user;
/**
* Setter and Getter
*/
}
that's how i run it
ProjectController Class
public String createProject(){
project.setProjectDate(new Date());
project.setProjectStatus(new ProjectStatusFacade().findByStatus("active"));
ProjectMember projectMember = new ProjectMember();
projectMember.setMemberStatus(new MemberStatusFacade().findByStatus("accepted"));
projectMember.setMemberRole(new MemberRoleFacade().findByRole("team leader"));
projectMember.setActivationDate(new Date());
projectMember.setUser(userSession.getUser());
new ProjectFacade().create(project);
System.out.print(project);
projectMember.setProject(project);
new ProjectMemberFacade().create(projectMember);
userSession.setUser(new UserFacade().findById(userSession.getUser().getUserId()));
return "index?faces-redirect=true";
}
and that's what i get in the end
Caused by: javax.faces.el.EvaluationException: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
... more exceptions
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
... more exceptions
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
...more exceptions
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`goent`.`projectmember`, CONSTRAINT `FKfyw2iinfhhsbrmqbu1sr7l93q` FOREIGN KEY (`projectMemberId`) REFERENCES `project` (`projectId`))
... more exceptions
15:51:06,449 ERROR [io.undertow.request] (default task-4) UT005023: Exception handling request to /hibernate/pages/project-add-member.xhtml: javax.servlet.ServletException: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
... more exceptions
Caused by: javax.faces.el.EvaluationException: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
... more exceptions
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
...more exceptions
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
... more exceptions
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`goent`.`projectmember`, CONSTRAINT `FKfyw2iinfhhsbrmqbu1sr7l93q` FOREIGN KEY (`projectMemberId`) REFERENCES `project` (`projectId`))
... more exceptions
Using: Java, JPA, Hibernate, MySQL5.7
The cause of exception is :
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`goent`.`projectmember`, CONSTRAINT `FKfyw2iinfhhsbrmqbu1sr7l93q` FOREIGN KEY (`projectMemberId`) REFERENCES `project` (`projectId`))
Your action is violating foreign key constraint for projectMemberId column in projectmember table, which is referencing projectId column of project table as per your defined specifications.
This is what most likely is happening.
In the Project entity, you are telling the persistence provider to always eagerly fetch the ProjectNames:
#OneToMany(mappedBy = "projectMemberId",fetch = FetchType.EAGER)
private List<ProjectMember> memberList = new ArrayList<ProjectMember>();
Then in the save method you are creating a ProjectName and populating it with the Project. Thats fine, though the list in the Project does not contain that newly created ProjectName.
The dependency has to be set on both sides, so eventually you would need to do following in your method:
project.getMemberList().add(projectName);
Thank you people, finally I could fix the bug. The problem was in Project class, it was about incorrect mapping. Instead of telling variable to map in other class, I was pointing on PK of that class.
I wrote this
Project class
#ManyToOne
#JoinColumn(name = "projectStatusId")
private ProjectStatus projectStatus;
instead this
//Correct code
#ManyToOne
#JoinColumn(name = "project")
private ProjectStatus projectStatus;
after this change the code started work well.
I am trying to do a one-to-many mapping using hibernate to insert some info into the DB but every time data is getting updated in the table rather than inserting a new row
I have 2 entities: ReportMaster and Reportdetail. where many Reportdetail data contain the ID which is Foreign key mapped to report master primary key column Id
#Entity
#Table(name = "ReportMaster")
public class ReportMaster implements Serializable {
private Integer repId;
private Set<ReportDetail> reportDetails = new HashSet<ReportDetail>();
#Id
#GeneratedValue
#Column(name = "RepId", unique = true, nullable = false)
public Integer getRepId() {
return this.repId;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "reportMaster")
public Set<ReportDetail> getReportDetails() {
return this.reportDetails;
}
2nd entity is:
#Entity
#Table(name = "ReportDetail")
public class ReportDetail implements Serializable {
private String repColumn;
private String colData;
//.......corresponding getters and setters
private ReportMaster reportMaster;
#ManyToOne(targetEntity = ReportMaster.class)
#JoinColumn(name = "RepId")
public ReportMaster getReportMaster() {
return this.reportMaster;
}
I want to insert a new row into the reportdetails table, but it is getting updated:
ReportMaster report=new ReportMaster(req.getReportName(), req.getCid(), req.getReportDesc(), new Date());
report.addDetail(new ReportDetail(repcol,desc);
getTemplate().save(obj);
The generated HQL is:
org.hibernate.SQL - insert into ReportMaster (CreateDate, CustomerID, RepDesc, ReportName) values (?, ?, ?, ?)
org.hibernate.SQL - update ReportDetail set RepId=? where ColData=? and RepColumn=?
2013-02-16 10:13:34,109[http-6060-1] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.jdbc.BatchedTooManyRowsAffectedException: Batch update returned unexpected row count from update [0]; actual row count: 2; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:71)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:24)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2403)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
You should set the property 'reportMaster' of ReportDetail like this:
ReportMaster report=new ReportMaster(req.getReportName(), req.getCid(),req.getReportDesc(), new Date());
// create detail and set its master
ReportDetail detail = new ReportDetail(repcol,desc)
detail.setReportMaster(report);
report.addDetail(detail);
getTemplate().save(obj);
Follow this document.
Hope this helps.
I've updated the question so that both tables now use auto-increment. Is perhaps the problem in persisting to the MESSAGES table a problem with the database schema?
In trying to persist a MessageBean as so:
private void persist(MessageBean messageBean) throws Exception {
LOG.info("loading.." + messageBean);
Messages message = new Messages(messageBean);
emf = Persistence.createEntityManagerFactory("USENETPU");
em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(message);
em.getTransaction().commit();
}
Stack trace:
run:
Jul 27, 2012 3:04:06 PM net.bounceme.dur.usenet.controller.CommentsDefaultListModel persist
INFO: loading..floor installer (cultas lake)
[EL Info]: 2012-07-27 15:04:10.006--ServerSession(30409723)--EclipseLink, version: Eclipse Persistence Services - 2.3.0.v20110604-r9504
[EL Info]: 2012-07-27 15:04:11.78--ServerSession(30409723)--file:/home/thufir/NetBeansProjects/USENET/build/classes/_USENETPU login successful
[EL Warning]: 2012-07-27 15:04:12.072--ClientSession(29574192)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'nntp.SEQUENCE' doesn't exist
Error Code: 1146
Call: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
bind => [2 parameters bound]
Query: DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?")
Jul 27, 2012 3:04:12 PM net.bounceme.dur.usenet.controller.CommentsDefaultListModel <init>
SEVERE: null
Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'nntp.SEQUENCE' doesn't exist
Error Code: 1146
Call: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
bind => [2 parameters bound]
Query: DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324)
From MySql:
mysql>
mysql>
mysql> show tables;
+----------------+
| Tables_in_nntp |
+----------------+
| comments |
| messages |
+----------------+
2 rows in set (0.00 sec)
mysql>
mysql> show create table comments;
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| comments | CREATE TABLE `comments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`message_id` int(11) NOT NULL,
`comment` text NOT NULL,
`stamp` date NOT NULL,
PRIMARY KEY (`id`),
KEY `message_id` (`message_id`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`message_id`) REFERENCES `messages` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
mysql> show create table messages;
+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| messages | CREATE TABLE `messages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`newsgroup` text NOT NULL,
`subject` text NOT NULL,
`content` text NOT NULL,
`number` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
and the fields for Messages:
package net.bounceme.dur.usenet.controller;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#Entity
#Table(name = "messages", catalog = "nntp", schema = "")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Messages.findAll", query = "SELECT m FROM Messages m"),
#NamedQuery(name = "Messages.findById", query = "SELECT m FROM Messages m WHERE m.id = :id")})
public class Messages implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "id", nullable = false)
#GeneratedValue
private Integer id;
#Basic(optional = false)
#Lob
#Column(name = "newsgroup", nullable = false, length = 65535)
private String newsgroup;
#Basic(optional = false)
#Lob
#Column(name = "subject", nullable = false, length = 65535)
private String subject;
#Basic(optional = false)
#Lob
#Column(name = "content", nullable = false, length = 65535)
private String content;
#Basic(optional = false)
#Lob
#Column(name = "number", nullable = false, length = 65535)
private String number;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "messageId")
private Collection<Comments> commentsCollection;
public Messages() {
}
And the Comments fields:
package net.bounceme.dur.usenet.controller;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "comments", catalog = "nntp", schema = "")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Comments.findAll", query = "SELECT c FROM Comments c"),
#NamedQuery(name = "Comments.findById", query = "SELECT c FROM Comments c WHERE c.id = :id"),
#NamedQuery(name = "Comments.findByStamp", query = "SELECT c FROM Comments c WHERE c.stamp = :stamp")})
public class Comments implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "id", nullable = false)
#GeneratedValue
private Integer id;
#Basic(optional = false)
#Lob
#Column(name = "comment", nullable = false, length = 65535)
private String comment;
#Basic(optional = false)
#Column(name = "stamp", nullable = false)
#Temporal(TemporalType.DATE)
private Date stamp;
#JoinColumn(name = "message_id", referencedColumnName = "id", nullable = false)
#ManyToOne(optional = false)
private Messages messageId;
public Comments() {
}
For mysql I would recommend you following:
At you table messages at field id add declaration auto_increment:
create table messages(
...
id int not null auto_increment,
...
primary key (id)
)
At entity declaration use
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
This talks to JPA use auto-increment feature of MySQL
If it is not applicable (for example you may want to create related another entity in the same transaction) use TABLE strategy (for more details see http://www.objectdb.com/java/jpa/entity/generated )
The AUTO strategy is an alias for NATIVE if your database supports it, or SEQUENCE if your database supports it, or TABLE if your database doesn't support any of those.
So if the database doesn't support NATIVE and SEQUENCE, then you need to create the table that EclipseLink uses to generate IDs.
With MySQL, NATIVE should be supported. You need to make the ID column an auto_increment column, though. Make sure to configure the appropriate DatabasePlatform as well.