I have two entities:
public class Field {
private String inputType;
#OneToMany(cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
mappedBy = "field")
#OrderBy("order_by")
private List<SelectItem> selectItems;
}
public class SelectItem {
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "field_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
private Field field;
private int orderBy;
}
It seems that Hibernate is ignoring the #OrderBy annotation in the Field class when selecting the SelectItems associated with a Field instance. I know this because 1) the ordering is not according to the orderBy value and 2) when I intentionally misspell the value in the #OrderBy annotation, everything still works.
In fact, I don't even see evidence in the log that Hibernate is even selecting from the select_items table. Something must be because when I look at the values being returned from the repository, the SelectItems are in there, but the query isn't printing in the log, as all the rest of the queries do.
This is from my log:
Hibernate: insert into fields (created_by, modified_by, modified_date, category, disabled, hidden, input_type, is_integer, label, max, min, name, is_number, order_by, positive_number, required, suffix, uuid, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into select_items (descr, field_id, order_by, selected, uuid, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into select_items (descr, field_id, order_by, selected, uuid, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into select_items (descr, field_id, order_by, selected, uuid, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into select_items (descr, field_id, order_by, selected, uuid, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into select_items (descr, field_id, order_by, selected, uuid, id) values (?, ?, ?, ?, ?, ?)
Hibernate: select field0_.id as id1_18_, field0_.created_by as created_2_18_, field0_.created_date as created_3_18_, field0_.modified_by as modified4_18_, field0_.modified_date as modified5_18_, field0_.category as category6_18_, field0_.disabled as disabled7_18_, field0_.hidden as hidden8_18_, field0_.input_type as input_ty9_18_, field0_.is_integer as is_inte10_18_, field0_.label as label11_18_, field0_.max as max12_18_, field0_.min as min13_18_, field0_.name as name14_18_, field0_.is_number as is_numb15_18_, field0_.order_by as order_b16_18_, field0_.positive_number as positiv17_18_, field0_.required as require18_18_, field0_.suffix as suffix19_18_, field0_.uuid as uuid20_18_ from fields field0_ where field0_.category=? and field0_.name=?
There is no subsequent select statement in the log that would pull the nested SelectItem instances--yet they are there when I get the object back.
So somehow they are being selected, but it doesn't appear that hibernate is doing it, and whatever is selecting them is ignoring the #OrderBy annotation.
Can someone please explain what's going on?
It is missing to specific order type ASC or DESC and call it directly by field name.
#OrderBy("orderBy ASC")
Related
Sorry it's maybe an easy question but I can't find anything on Google. I'm parsing csvData with e.g. more than 100000 rows / objects. I want to check that ALL values for the attributes are valid before they get written into the database. Annotations like #Size or #Length do not help...
To give you an example:
Entity:
#Entity
#Data
public class Transaction {
#Size(max = 30)
private String timestamp;
}
The csv is parsed and the objects are written down in a List.
List<Transaction> transaction = new ArrayList<>();
// list will be filled
try {
databaseConnector.saveAllTransactions(transaction, transactionRepository);
} catch (ConstraintViolationException exc) {
System.out.println(exc.getMessage());
}
The error that appears after the 5th object.
Hibernate: insert into transaction (amount, customer_customer_id, discount, receipt_no, receipt_pos_no, timestamp, unit_price) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into transaction (amount, customer_customer_id, discount, receipt_no, receipt_pos_no, timestamp, unit_price) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into transaction (amount, customer_customer_id, discount, receipt_no, receipt_pos_no, timestamp, unit_price) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into transaction (amount, customer_customer_id, discount, receipt_no, receipt_pos_no, timestamp, unit_price) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into transaction (amount, customer_customer_id, discount, receipt_no, receipt_pos_no, timestamp, unit_price) values (?, ?, ?, ?, ?, ?, ?)
Validation failed for classes [com.stuff.project.entity.Transaction] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='muss zwischen 0 und 30 liegen', propertyPath=timestamp, rootBeanClass=class com.stuff.project.entity.Transaction, messageTemplate='{javax.validation.constraints.Size.message}'}
]
Only that you know how the method looks like.
public boolean saveAllTransactions(List<Transaction> transactions, TransactionRepository transactionRepository) {
transactionRepository.saveAll(transactions);
return true;
}
The only thing I could imagine is to go through the whole list of objects and check for each object the attributes for it's length like:
transactions.forEach(e -> e.getTimestamp().length != 30); ....
That does not seem to be very performance friendly...
First of all: performance shouldn't be your primary concern. You have a list with N entries, and when you want to check the string length for each of the N entries, hey: you have to iterate the N entries, and look at each one. Of course, you could theoretically do that in parallel, which, given "enough" data to work with, makes things quicker, at the cost of more CPU power being used.
The real problem: you start to implement "extra validation", instead of relying on your annotations. In other words: you are working "around" your framework. That is rarely a good idea.
Assuming we are talking generic Java (bean) annotations, the canonical answer would be to do two things:
to create a class that represents a list of your Transaction objects
to provide a custom validator that works on that list (and that knows to iterate all entries, and check that string length)
I use MySQL database, I want to update a date column, console show this info:
update license_user SET account = ?, password = ?, salt = ?, status = ?, type = ?, email = ?, phone = ?, lastLoginDate = ?, lastLoginIp = ?, createDate = ? where id = ?
[com.manji.persist.mapper.UserEntityMapper.updateByPrimaryKeySelective]-[DEBUG] - ==> Parameters: usertest_(String), Tx+G003oENaw9OtwBsEasQ==(String), 9876463965d11612c1c65cc01c6214d3(String), 0(Integer), 0(Integer), xxxxxxxxx#126.com(String), xxxxxxxxx(String), 2017-01-26 16:34:29.498(Timestamp), 127.0.0.1(String), 2017-01-11 14:00:00.0(Timestamp), 4(Long)
Date value is 2017-01-26 16:34:29.498, but database insert a different value 2017-01-26 02:34:29,I don't know how to solve this problem, can you give me some advice,thx very much.
When I try with Spring to udpdate the user with different values, but, for example, without modifying nickname:
//TODO: encripta contraseña monitorDao
public void updateMonitor(Monitor monitor){
BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor();
String contrasenya = passwordEncryptor.encryptPassword(monitor.getContrasenya());
this.jdbcTemplate.update(
"update Usuario set nickname=?, nombre= ?, apellidos= ?, email= ?, contrasenya = ?, especialidades = ?, telefono = ?",
monitor.getNickname(), monitor.getNombre(), monitor.getApellidos(), monitor.getEmail(),
contrasenya, monitor.getEspecialidades(), monitor.getTelefono()
);
}
This happens:
Request processing failed; nested exception is
org.springframework.dao.DuplicateKeyException:
PreparedStatementCallback; SQL [update Usuario set nickname=?, nombre=
?, apellidos= ?, email= ?, contrasenya = ?, especialidades = ?,
telefono = ?]; ERROR: duplicate key value violates unique constraint
"pk_usuario"
I've never used JDBC templates but it looks like you don't have a where clause in your SQL so you're updating all rows in the database to have those values. You need to restrict it to a single user by adding a where clause:
this.jdbcTemplate.update(
"update Usuario set nickname=?, nombre= ?, apellidos= ?, email= ?, contrasenya = ?, especialidades = ?, telefono = ? where nickname=?",
monitor.getNickname(), monitor.getNombre(), monitor.getApellidos(), monitor.getEmail(),
contrasenya, monitor.getEspecialidades(), monitor.getTelefono(), monitor.getNickname()
);
See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html#jdbc-JdbcTemplate-examples-update
In my opinion you should try this:
this.jdbcTemplate.update(
"update Usuario set nombre= ?, apellidos= ?, email= ?, contrasenya = ?, especialidades = ?, telefono = ? where nickname=?",
monitor.getNombre(), monitor.getApellidos(), monitor.getEmail(),
contrasenya, monitor.getEspecialidades(), monitor.getTelefono(), monitor.getNickname()
);
This won't update the nickname.
I configured a "question-tag" Many-to-Many relationship.in Hibernate
When I test it with a small program, it has the follwing error:
(My Hibernate version is 3.1)
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into javaqa2.qa_tag (creator_id, name, description, create_date, used_cnt) values (?, ?, ?, ?, ?)
Hibernate: insert into javaqa2.qa_tag (creator_id, name, description, create_date, used_cnt) values (?, ?, ?, ?, ?)
Hibernate: insert into javaqa2.qa_question (creator_id, subject, content, creator_ip, question_tags, upvote_cnt, downvote_cnt, visit_cnt, answer_cnt, comment_cnt, istopmost, islocked, isanonym, create_date) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into qa_question_tags (question_id, tag_id) values (?, ?)
Hibernate: insert into qa_question_tags (question_id, tag_id) values (?, ?)
Exception in thread "main" org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:143)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:333)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at test.Test1.main(Test1.java:49)
Caused by: java.sql.BatchUpdateException: No database selected
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1669)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1085)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
... 8 more
This is my Test Program:
public class Test1 {
public static void main(String[] args) {
Configuration cfg=new Configuration().configure();
SessionFactory sf=cfg.buildSessionFactory();
Session session = sf.openSession();
Transaction trans = session.beginTransaction();
Student student = (Student)session.load(Student.class, Integer.valueOf(45));
Question question=new Question(student, "test8881","test8882",
"192.168,88.88","Java,dotNet,Struts2", 0,0,0,0,0,
Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
new Date());
Tag tag1=new Tag(student,"test tag1","test tag1",new Date(),0);
Tag tag2=new Tag(student,"test tag2","test tag2",new Date(),0);
session.save(tag1);
session.save(tag2);
Set<Tag> tagList =new HashSet<Tag>();
tagList.add(tag1);
tagList.add(tag2);
question.setTags(tagList); // when add this line... error occurs
session.save(question);
trans.commit();
}
This program runs well when the method setTags(tagList) is not called for question,
however, when I add this method call, the error occurs. (see the comment in the program).
This is the portion of Question.hbm.xml defined Many-to-Many properties.
<set name="tags" table="qa_question_tags" lazy="true" cascade="all">
<key column="question_id"/>
<many-to-many class="model.Tag" column="tag_id"/>
</set>
I have set the following property in my hibernate.cfg.xml to ensure the table will be updated automatically.
<property name="hbm2ddl.auto"> update </property>
I was confused with the error message, and please tell me where is the wrong?
I have found the point in my hibernate queries, thanks for the patience and carefulness of #Andy Defresne .
In the log below:
Hibernate: insert into javaqa2.qa_tag (creator_id, name, description, create_date, used_cnt) values (?, ?, ?, ?, ?)
Hibernate: insert into javaqa2.qa_tag (creator_id, name, description, create_date, used_cnt) values (?, ?, ?, ?, ?)
Hibernate: insert into javaqa2.qa_question (creator_id, subject, content, creator_ip, question_tags, upvote_cnt, downvote_cnt, visit_cnt, answer_cnt, comment_cnt, istopmost, islocked, isanonym, create_date) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into qa_question_tags (question_id, tag_id) values (?, ?)
Hibernate: insert into qa_question_tags (question_id, tag_id) values (?, ?)
The last two lines of "insert into qa_question_tags" are absent of "javaqa." catalog.
So I add the following property catalog="javaqa2" in the Question.hbm.xml :
<set name="tags" table="qa_question_tags" lazy="true" cascade="all" catalog="javaqa2">
<key column="question_id"/>
<many-to-many class="model.Tag" column="tag_id"/>
</set>
Then the problem is solved and the error disappears.
To be complete , I post my Question.hbm.xml, and found catalog properties set in the <class> tag is not enough, it must be set in the <set> tag again:
<hibernate-mapping>
<class name="model.Question" table="qa_question" catalog="javaqa2">
...
<set name="tags" table="qa_question_tags" lazy="true" cascade="all" catalog="javaqa2">
<key column="question_id"/>
<many-to-many class="model.Tag" column="tag_id"/>
</set>
</class>
</hibernate-mapping>
I am sorry that i ask a very stupid question but i cant find the place where i miss the comma in the code..
sqlStr.append("INSERT INTO DS_GOAL ");
sqlStr.append("(DS_SITE_CODE, DS_FINANCIAL_YEAR, DS_DEPARTMENT_CODE, DS_PLAN_ID, DS_GOAL_ID, ");
sqlStr.append("DS_DESC, TO_CHAR(DS_PLAN_END_DATE, \"dd/MM/YY\"),");
sqlStr.append("DS_CORP_OBJECTIVE, DS_CORP_OBJECTIVE_OTHER, DS_FOCUS, DS_FOCUS_OTHER, ");
sqlStr.append("DS_TOTAL, DS_EQUIPMENT, DS_RECRUIT, DS_FTE, ");
sqlStr.append("DS_CREATED_USER, DS_MODIFIED_USER, DS_GOAL_ORDER ) ");
sqlStr.append("VALUES ");
sqlStr.append("(?, ?, ?, ?, ?,");
sqlStr.append("?, ?,");
sqlStr.append("?, ?, ?, ?,");
sqlStr.append("?, ?, ?, ?,");
sqlStr.append("?, ?, ?)");
sqlStr_insertGoal = sqlStr.toString();
After the
sqlStr.toString()
the console shows
INSERT INTO DS_GOAL (DS_SITE_CODE, DS_FINANCIAL_YEAR, DS_DEPARTMENT_CODE, DS_PLAN_ID,
DS_GOAL_ID,
DS_DESC, TO_CHAR(DS_PLAN_END_DATE, 'dd/MM/YYYY'),
DS_CORP_OBJECTIVE, DS_CORP_OBJECTIVE_OTHER, DS_FOCUS, DS_FOCUS_OTHER,
DS_TOTAL, DS_EQUIPMENT, DS_RECRUIT,
DS_FTE, DS_CREATED_USER, DS_MODIFIED_USER, DS_GOAL_ORDER)
VALUES (?, ?, ?, ?, ?,?, ?,?, ?, ?, ?,?, ?, ?, ?,?, ?, ?)
After Edited the code
the console shows
INSERT INTO DS_GOAL (DS_SITE_CODE, DS_FINANCIAL_YEAR, DS_DEPARTMENT_CODE, DS_PLAN_ID,
DS_GOAL_ID,
DS_DESC, DS_PLAN_END_DATE,
DS_CORP_OBJECTIVE, DS_CORP_OBJECTIVE_OTHER, DS_FOCUS, DS_FOCUS_OTHER,
DS_TOTAL, DS_EQUIPMENT, DS_RECRUIT,
DS_FTE, DS_CREATED_USER, DS_MODIFIED_USER, DS_GOAL_ORDER)
VALUES (?, ?, ?, ?, ?,?, TO_CHAR(DS_PLAN_END_DATE, 'dd/MM/YYYY'),?, ?, ?, ?,?, ?, ?,
?,?, ?, ?)
But the consoles shows invalid column index error
Thanks for help
I suspect your problem isn't actually a case of a missing comma (in my experience ORA errors are notorious for telling you the wrong thing). My suspicion is that your real issue is the use of " around the format string in your TO_CHAR call. To demonstrate, try this:
SELECT TO_CHAR(SYSDATE, "dd/MM/YY")
FROM DUAL;
If I run the above I get an ORA-00904: "dd/MM/YY": invalid identifier error. If I change the quotes to apostrophes instead:
SELECT TO_CHAR(SYSDATE, 'dd/MM/YY')
FROM DUAL;
I get 16/04/14. Double quotes are for identifiers, not strings:
SELECT TO_CHAR(SYSDATE, 'dd/MM/YY') AS "The Date"
FROM DUAL; // ^ This is an identifier
prints:
The Date
--------
16/04/14
EDIT:
Sorry, I should have spotted this one sooner! You're using TO_CHAR in your columns list, which you can't do. The below example nicely produces an ORA-00917: missing comma error:
CREATE TABLE JON_TEST (COL1 VARCHAR2(20));
COMMIT;
INSERT INTO JON_TEST (TO_CHAR(COL1, 'DD/MM/YYYY'))
VALUES (SYSDATE);
Whereas this works:
INSERT INTO JON_TEST (COL1)
VALUES (TO_CHAR(SYSDATE, 'dd/MM/YYYY'));
So you need to correct three things:
You need to change TO_CHAR to TO_DATE, and
You need to move the call to TO_DATE to your VALUES clause, and
You need to ensure that you use ' instead of " with the format string.
This is how Oracle define the syntax for INSERT statements:
Notice that in the middle section that it only says column_name and not sql_expression.
Try changing your query to the following:
sqlStr.append("INSERT INTO DS_GOAL ")
.append("(DS_SITE_CODE, DS_FINANCIAL_YEAR, DS_DEPARTMENT_CODE, DS_PLAN_ID, DS_GOAL_ID, ")
.append("DS_DESC, DS_PLAN_END_DATE, ")
.append("DS_CORP_OBJECTIVE, DS_CORP_OBJECTIVE_OTHER, DS_FOCUS, DS_FOCUS_OTHER, ")
.append("DS_TOTAL, DS_EQUIPMENT, DS_RECRUIT, DS_FTE, ")
.append("DS_CREATED_USER, DS_MODIFIED_USER, DS_GOAL_ORDER ) ")
.append("VALUES ")
.append("(?, ?, ?, ?, ?,")
.append("?, TO_DATE(?, 'dd/MM/YY'),")
.append("?, ?, ?, ?,")
.append("?, ?, ?, ?,")
.append("?, ?, ?)");
sqlStr_insertGoal = sqlStr.toString();