Spring Data JDBC aggregate ID in child objects - spring-boot

I was playing with Spring-Data-JDBC and encountered 2 issues. I have following entities with 1:N relationship.
------
DROP TABLE IF EXISTS product;
CREATE TABLE product (
product_id int AUTO_INCREMENT PRIMARY KEY,
name varchar(250) not null,
description varchar(512) not null
);
DROP TABLE IF EXISTS product_line;
CREATE TABLE product_line (
product_id int constraint fk_product_line_product references product(product_id),
label varchar(250) not null
);
----------
#Data
#Builder
public class Product {
#Id
private Long productId;
private String name;
private String description;
#Singular
#MappedCollection(idColumn = "product_id", keyColumn = "product_id")
private Set<ProductLine> lines;
}
#Data
#Builder
public class ProductLine {
private Long productId;
private String label;
}
Problem 1: Following test case fails because I was expecting to have the productId populated in the ProductLine object but it is not. Is this the expected behavior of Spring Data JDBC?
#SpringBootTest
class SpringDataJdbcApplicationTests {
#Autowired
private ProductRepository productRepository;
#Test
void saveTest() {
Product product = Product.builder()
.name("Product-1")
.description("Description")
.line(ProductLine
.builder()
.label("Line-label")
.build())
.build();
this.productRepository.save(product);
assertThat(product.getProductId()).isNotNull();
assertThat(product.getLines()).isNotNull().isNotEmpty().hasSize(1);
assertThat(product.getLines().stream().findFirst()).isPresent();
assertThat(product.getLines().stream().findFirst().get().getProductId()).isNotNull().isEqualTo(product.getProductId()); // -----> Fails here.
}
}
Problem 2: If I change Set<ProductLine> to List<ProductLine>, it fails due to JdbcSQLIntegrityConstraintViolationException, which means the product id set to 0 as seen in the log snippet below.
2022-09-10 22:33:12.393 DEBUG 18460 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT INTO "PRODUCT_LINE" ("LABEL", "PRODUCT_ID") VALUES (?, ?)]
2022-09-10 22:33:12.393 TRACE 18460 --- [ main] o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 1, parameter value [Line-label], value class [java.lang.String], SQL type 12
2022-09-10 22:33:12.393 TRACE 18460 --- [ main] o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 2, parameter value [0], value class [java.lang.Integer], SQL type 4

Following test case fails because I was expecting to have the productId populated in the ProductLine object but it is not. Is this the expected behavior of Spring Data JDBC?
Yes, if you want a productId you have to (and can easily) populate it yourself using plain Java code.
But you really shouldn't need the productId in the first place since if you follow Domain Driven Design, you will access a ProductLine exclusively from a Product which already has the id at hand.
The article https://spring.io/blog/2021/09/22/spring-data-jdbc-how-do-i-make-bidirectional-relationships might be helpful.
If I change Set<ProductLine> to List<ProductLine>, it fails due to JdbcSQLIntegrityConstraintViolationException, which means the product id set to 0 as seen in the log snippet below.
You have two problems here:
You already have two sources for the product_id field: The relation from the aggregate root and the simple field, which may cause problems.
You mapped both the back reference to the aggregate root idColumn and the index of the list keyColumn to the same database column. Together with the simple field from above these are three values all mapped to the same column. Not good.
The value that seems to win is the list index, resulting in the exception.
In order to fix that, create an additional column in the product_line table and map the list index to it.

Related

QueryDSL Predicate for use with JPARepository where field is a JSON String converted using an AttributeConverter to a List<Object>

I have a JPA Entity (Terminal) which uses an AttributeConverter to convert a Database String into a list of Objects (ProgrmRegistration). The converter just uses a JSON ObjectMapper to turn the JSON String into POJO objects.
Entity Object
#Entity
#Data
public class Terminal {
#Id
private String terminalId;
#NotEmpty
#Convert(converter = ProgramRegistrationConverter.class)
private List<ProgramRegistration> programRegistrations;
#Data
public static class ProgramRegistration {
private String program;
private boolean online;
}
}
The Terminal uses the following JPA AttributeConverter to serialize the Objects from and to JSON
JPA AttributeConverter
public class ProgramRegistrationConverter implements AttributeConverter<List<Terminal.ProgramRegistration>, String> {
private final ObjectMapper objectMapper;
private final CollectionType programRegistrationCollectionType;
public ProgramRegistrationConverter() {
this.objectMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
this.programRegistrationCollectionType =
objectMapper.getTypeFactory().constructCollectionType(List.class, Terminal.ProgramRegistration.class);
}
#Override
public String convertToDatabaseColumn(List<Terminal.ProgramRegistration> attribute) {
if (attribute == null) {
return null;
}
String json = null;
try {
json = objectMapper.writeValueAsString(attribute);
} catch (final JsonProcessingException e) {
LOG.error("JSON writing error", e);
}
return json;
}
#Override
public List<Terminal.ProgramRegistration> convertToEntityAttribute(String dbData) {
if (dbData == null) {
return Collections.emptyList();
}
List<Terminal.ProgramRegistration> list = null;
try {
list = objectMapper.readValue(dbData, programRegistrationCollectionType);
} catch (final IOException e) {
LOG.error("JSON reading error", e);
}
return list;
}
}
I am using Spring Boot and a JPARepository to fetch a Page of Terminal results from the Database.
To filter the results I am using a BooleanExpression as the Predicate. For all the filter values on the Entity it works well, but the List of objects converted from the JSON string does not allow me to easily write an Expression that will filter the Objects in the list.
REST API that is trying to filter the Entity Objects using QueryDSL
#GetMapping(path = "/filtered/page", produces = MediaType.APPLICATION_JSON_VALUE)
public Page<Terminal> findFilteredWithPage(
#RequestParam(required = false) String terminalId,
#RequestParam(required = false) String programName,
#PageableDefault(size = 20) #SortDefault.SortDefaults({ #SortDefault(sort = "terminalId") }) Pageable p) {
BooleanBuilder builder = new BooleanBuilder();
if (StringUtils.isNotBlank(terminalId))
builder.and(QTerminal.terminal.terminalId.upper()
.contains(StringUtils.upperCase(terminalId)));
// TODO: Figure out how to use QueryDsl to get the converted List as a predicate
// The code below to find the programRegistrations does not allow a call to any(),
// expects a CollectionExpression or a SubqueryExpression for calls to eqAny() or in()
if (StringUtils.isNotBlank(program))
builder.and(QTerminal.terminal.programRegistrations.any().name()
.contains(StringUtils.upperCase(programName)));
return terminalRepository.findAll(builder.getValue(), p);
}
I am wanting to get any Terminals that have a ProgramRegistration object with the program name equal to the parameter passed into the REST service.
I have been trying to get CollectionExpression or SubQueryExpression working without success since they all seem to be wanting to perform a join between two Entity objects. I do not know how to create the path and query so that it can iterate over the programRegistrations checking the "program" field for a match. I do not have a QProgamRegistration object to join with, since it is just a list of POJOs.
How can I get the predicate to match only the Terminals that have programs with the name I am searching for?
This is the line that is not working:
builder.and(QTerminal.terminal.programRegistrations.any().name()
.contains(StringUtils.upperCase(programName)));
AttributeConverters have issues in Querydsl, because they have issues in JPQL - the query language of JPA - itself. It is unclear what actually the underlying query type of the attribute is, and whether the parameter should be a basic type of that query type, or should be converted using the conversion. Such conversion, whilst it appears logical, is not defined in the JPA specification. Thus a basic type of the query type needs to be used instead, which leads to new difficulties, because Querydsl can't know the type it needs to be. It only knows the Java type of the attribute.
A workaround can be to force the field to result into a StringPath by annotating the field with #QueryType(PropertyType.STRING). Whilst this fixes the issue for some queries, you will run into different issues in other scenarios. For more information, see this thread.
Although the following desired QueryDsl looks like it should work
QTerminal.terminal.programRegistrations.any().name().contains(programName);
In reality JPA would never be able to convert it into something that would make sense in terms of SQL. The only SQL that JPA could convert it into could be as follows:
SELECT t.terminal_id FROM terminal t where t.terminal_id LIKE '%00%' and t.program_registrations like '%"program":"MY_PROGRAM_NAME"%';
This would work in this use case, but be semantically wrong, and therefore it is correct that it should not work. Trying to select unstructured data using a structured query language makes no sense
The only solution is to treat the data as characters for the DB search criteria, and to treat it as a list of Objects after the query completes and then perform filtering of the rows in Java. Although This makes the paging feature rather useless.
One possible solution is to have a secondary read only String version of the column that is used for the DB search criteria, that is not converted to JSON by the AttributeConverter.
#JsonIgnore
#Column(name = "programRegistrations", insertable = false, updatable = false)
private String programRegistrationsStr;
The real solution is do not use unstructured data when you want structured queries on that data Therefore convert the data to either a database that supports the JSON natively for queries or model the data correctly in DDL.
To have a short answer: the parameter used in the predicate on attribute with #QueryType must be used in another predicate on attribute of type String.
It's a clearly known issue describe in this thread: https://github.com/querydsl/querydsl/issues/2652
I simply want to share my experience about this bug.
Model
I have an entity like
#Entity
public class JobLog {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
#QueryType(PropertyType.STRING)
private LocalizedString message;
}
Issue
I want to perform some predicate about message. Unfortunately, with this configuration, I can't do this:
predicates.and(jobLog.message.likeIgnoreCase(escapedTextFilter));
because I have the same issues that all people!
Solution
But I find a way to workaround :)
predicates.and(
(jobLog.id.likeIgnoreCase(escapedTextFilter).and(jobLog.id.isNull()))
.or(jobLog.message.likeIgnoreCase(escapedTextFilter)));
Why it workaround the bug?
It's important that escapedTextFilter is the same in both predicate!
Indeed, in this case, the constant is converter to SQL in the first predicate (which is of String type). And in the second predicate, we use the conterted value
Bad thing?
Add a performance overflow because we have OR in predicate
Hope this can help someone :)
I've found one way to solve this problem, my main idea is to use mysql function cast(xx as char) to cheat hibrenate. Below is my base info. My code is for work , so I've made an example.
// StudentRepo.java
public interface StudentRepo<Student, Long> extends JpaRepository<Student, Long>, QuerydslPredicateExecutor<Student>, JpaSpecificationExecutor<Student> {
}
// Student.java
#Data
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode(of = "id")
#Entity
#Builder
#Table(name = "student")
public class Student {
#Convert(converter = ClassIdsConvert.class)
private List<String> classIds;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
// ClassIdsConvert.java
public class ClassIdsConvert implements AttributeConverter<List<String>, String> {
#Override
public String convertToDatabaseColumn(List<String> ips) {
// classid23,classid24,classid25
return String.join(",", ips);
}
#Override
public List<String> convertToEntityAttribute(String dbData) {
if (StringUtils.isEmpty(dbData)) {
return null;
} else {
return Stream.of(dbData.split(",")).collect(Collectors.toList());
}
}
}
my db is below
id
classIds
name
address
1
2,3,4,11
join
北京市
2
2,31,14,11
hell
福建省
3
2,12,22,33
work
福建省
4
1,4,5,6
ouy
广东省
5
11,31,34,22
yup
上海市
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL,
`classIds` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
Use JpaSpecificationExecutor solve the problem
Specification<Student> specification = (root, query, criteriaBuilder) -> {
String classId = "classid24"
String classIdStr = StringUtils.wrap(classId, "%");
var predicate = criteriaBuilder.like(root.get("classIds").as(String.class), classIdStr);
return criteriaBuilder.or(predicate);
};
var students = studentRepo.findAll(specification);
log.info(new Gson().toJson(students))
attention the code root.get("classIds").as(String.class)
In my opinion, if I don't add .as(String.class) , hibernate will think the type of student.classIds is list and throw an Exception as below.
SQL will like below which runs correctly in mysql. But hibnerate can't work.
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [%classid24%] did not match expected type [java.util.List (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [%classid24%] did not match expected type [java.util.List (n/a)]
SELECT
student0_.id AS id1_0_,
student0_.class_ids AS class_ids2_0_
FROM
student student0_
WHERE
student0_.class_ids LIKE '%classid24%' ESCAPE '!'
if you add .as(String.class) , hibnerate will think the type of student.classIds as string and won't check it at all.
SQL will be like below which can run correct in mysql. Also in JPA.
SELECT
student0_.id AS id1_0_,
student0_.class_ids AS class_ids2_0_
FROM
student student0_
WHERE
cast( student0_.class_ids AS CHAR ) LIKE '%classid24%' ESCAPE '!'
when the problem is solved by JpaSpecificationExecutor, so I think this can be solve also in querydsl. At last I find the template idea in querydsl.
String classId = "classid24";
StringTemplate st = Expressions.stringTemplate("cast({0} as string)", qStudent.classIds);
var students = Lists.newArrayList<studentRepo.findAll(st.like(StringUtils.wrap(classId, "%"))));
log.info(new Gson().toJson(students));
it's sql is like below.
SELECT
student0_.id AS id1_0_,
student0_.class_ids AS class_ids2_0_
FROM
student student0_
WHERE
cast( student0_.class_ids AS CHAR ) LIKE '%classid24%' ESCAPE '!'

how to map custom sql query to model to load on jsp view in spring

I am beginner in spring. I want to show SQL data to JSP view page.
This is my SQL table
create table customer(
id int primary key,
name varchar(250),
salary int,
manager_id int
)
and I am trying to show data from this query
select m.id, m.name, m.salary, n.name from customer m, customer n where n.id=m.manager_id
So basically from this query, I am trying to show ID int, name varchar, salary int, manager_name varchar.
I have create the entity java class as below
#Entity
#Table(name="customer")
public class Customer{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int id;
#Column
private String name;
#Column(name="manager_id")
private String manager;
#Column(name="salary")
private int salary;
............
............
}
This is the code of my DAO class
Session session= entityManager.unwrap(Session.class);
Query<Employee> query= session.createQuery(<above sql query need to add here?>,Customer.class);
return query.getResultList();
So the issues are,
This SQL query return the data which could not be matched to Customer Entity class. So do I need to create another Entity class for this? Is there any better way?
The above required SQL query is not able to execute. What the correct way to execute custom SQL query?
Regarding your first question: Yes there is better way. you can directly fetch the results in a projection dto class. take a at: https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/
About your second question: What Do you mean by saying the query does not execute?
Can you give us the Exception/Stacktrace? Did you try to execute the query (sql form of it) physically? Does it run then?

Why doesn't Mybatis map a simple ENUM correctly?

I'm not doing anything out of the ordinary from what I can tell. I have a spring boot application using mybatis:
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'
I have an application.properties config for mybatis that is pretty simple:
## MyBatis ##
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-statement-timeout=30
My database table looks like this:
CREATE TABLE workspace_external_references (
id CHAR(36) PRIMARY KEY,
workspace_id CHAR(36) NOT NULL,
site VARCHAR(255) NOT NULL,
external_id VARCHAR(255) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT NOW(6),
updated_at DATETIME(6) NOT NULL DEFAULT NOW(6),
FOREIGN KEY (workspace_id) REFERENCES workspaces (id) ON DELETE CASCADE
)
With just a single entry like this:
'a907c0af-216a-41e0-b16d-42107a7af05f', 'e99e4ab4-839e-405a-982b-08e00fbfb2d4', 'ABC', '6', '2020-06-09 00:19:20.135822', '2020-06-09 00:19:20.135822'
In my mapper file I'm doing a select of all references like this:
#Select("SELECT * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(#Param("workspaceId") final UUID workspaceId);
And the java object that this is supposed to map to looks like this:
public class WorkspaceExternalReference {
private UUID id;
private UUID workspaceId;
private Sites site;
private String externalId;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public WorkspaceExternalReference(
final Sites site,
final UUID workspaceId,
final String externalId) {
this.site = site;
this.workspaceId = workspaceId;
this.externalId = externalId;
}
}
public enum Sites {
ABC, XYZ;
}
Sooooo why doesn't this work? I get this error back:
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'id' from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.acme.Sites.a907c0af-216a-41e0-b16d-42107a7af05f
When there is no default constructor, you need to let MyBatis know which columns to pass to the constructor explicitly (in most cases).
With annotations, it would look as follows.
You can use <resultMap> and <constructor> in XML mapper.
#ConstructorArgs({
#Arg(column = "site", javaType = Sites.class),
#Arg(column = "workspace_id", javaType = UUID.class),
#Arg(column = "external_id", javaType = String.class)
})
#Select("SELECT * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(#Param("workspaceId") final UUID workspaceId);
Other columns (i.e. id, created_at, updated_at) will be auto-mapped via setters (if there are) or reflection.
Alternatively, you can just add the default (no-arg) constructor to the WorkspaceExternalReference class. Then all columns will be auto-mapped after the class is instantiated.
Note: To make it work, there needs to be a type handler registered for UUID, but you seem to have done it already (otherwise the parameter mapping wouldn't work).

spring.jpa.hibernate.ddl-auto=update property alters the foreign key every time

I am using spring.jpa.hibernate.ddl-auto=update property to update the schema.
As per my understanding if we do changes in the entity then table schema gets updated.
But on spring boot app startup every time alter command gets executed for the foreign key.
Following is the entity.
#Entity
#Table(name = "feedback")
#Data
public class Feedback implements Serializable {
private static final long serialVersionUID = -6420805626682233375L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "study_id")
#JsonIgnore
private Study study;
#ManyToOne(fetch= FetchType.EAGER)
#JoinColumn(name="user_id", nullable = false)
private User user;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "feedback_date", nullable = false)
private Date feedbackDate;
#Size(max = 1000)
#Column(name = "feedback", length = 1000)
private String feedback;
}
In entity you can see I have following two property for that foreign key gets created on spring boot app starts first time:
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "study_id")
#JsonIgnore
private Study study;
#ManyToOne(fetch= FetchType.EAGER)
#JoinColumn(name="user_id", nullable = false)
private User user;
So when I am restarting the app or saving the code every time foreign key constraints gets altered even if I am not changing that relationship(property).
2018-12-05 18:44:12.027 INFO 22736 --- [ restartedMain] c.d.smartviewer.SmartViewerApplication : Starting SmartViewerApplication on LAPTOP-F95LLCU3 with PID 22736 (D:\Sagar_\SVN\SmartViewer\target\classes started by ASUS in D:\Sagar_\SVN\SmartViewer)
2018-12-05 18:44:12.027 DEBUG 22736 --- [ restartedMain] c.d.smartviewer.SmartViewerApplication : Running with Spring Boot v2.0.6.RELEASE, Spring v5.0.10.RELEASE
2018-12-05 18:44:12.027 INFO 22736 --- [ restartedMain] c.d.smartviewer.SmartViewerApplication : No active profile set, falling back to default profiles: default
2018-12-05 18:44:13.356 INFO 22736 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1329 ms
Hibernate: alter table annotation add constraint FK7hwy1g5myfk7grmm2j7faqggd foreign key (parent_id) references annotation (id)
Hibernate: alter table feedback add constraint FKfxt8nk3jikofi3x40bsjd00vt foreign key (study_id) references study (id)
Hibernate: alter table feedback add constraint FK7k33yw505d347mw3avr93akao foreign key (user_id) references user (id)
Hibernate: alter table hospital add constraint FK3922fhj7qnyc3bw5x8xl6m6xc foreign key (contact_1) references contact (id)
So what should I change to not execute alter command for the foreign key if I do not change the foreign key entity property?
Constraints are part of a database schema definition.
Constraints are the rules enforced on the data columns of a table. These are used to limit the type of data that can go into a table. This ensures the accuracy and reliability of the data in the database. Constraints could be either on a column level or a table level. The column level constraints are applied only to one column, whereas the table level constraints are applied to the whole table.
kinds of constraints are:
NOT NULL− Ensures that a column cannot have NULL value.
DEFAULT - Provides a default value for a column when none is specified.
UNIQUE - Ensures that all values in a column are different.
PRIMARY KEY - Uniquely identifies each row/record in a database table.
FOREIGN KEY - Uniquely identifies a row/record in any of the given database table.
CHECK CONSTRAINT - The CHECK constraint ensures that all the values in a column satisfies certain conditions.
INDEX - Used to create and retrieve data from the database very quickly.
Q : Is this constraint in hibernate optional or cancel to update ?
A : No. it is not optional, it is needed for relational entity.
You can also define this constraint in your DB to changes while run time if necessary but be careful not recommended.
I think this is a bug for hibernate to alter every time base on this below link (same problem):
https://discourse.hibernate.org/t/manytoone-alter-table-query-is-generating-every-time-when-inserting-a-value/1162/6

Selecting from a view in H2 doesn't work

I recently replaced PostgreSql unit test database with an in memory H2 Database. I couldn't figure out why couple tests are failing, it was working fine with Postgre. There are approx. 280+ unit tests in this application. The failing dao tests are selecting from a view and the entity has a EmbeddedId, those the columns of that view.
See below code (Note: I changed names, code and the sql to hide the real names when writing this email, but this was a working unit test with Postgre db)
<pre>
#Table(name = "item_view") // <- item_view is a database view
public class ItemV implements Serializable
{
.....
#EmbeddedId // <- entity has an embedded id
private ItemVId id;
.....
#Embeddable
public static class ItemVId implements Serializable //<- This is the embeddedId
{
#Column(name = "item_id", updatable=false, insertable=false)
private Long ItemId; //<- col no.1 of view
#Column(name = "item_type_id", updatable=false, insertable=false)
private Integer ItemTypeId; //<- col no.2 of view
.....
ItemType is an enum
And the view is
CREATE OR REPLACE VIEW item_view AS
( ( ( SELECT pt.id as item_id, cit.id as item_type_id
FROM xyz pt, item_type cit
WHERE pt.name::text = 'xyz'::text
UNION
SELECT z.id as item_id, cit.id as item_type_id
FROM zzz z, item_type cit
WHERE z.name::text = 'zzz'::text)
..............
and the dao method is
public ItemView find(Long itemId, ItemType itemType)
{
String hql = " from ItemV iv where iv.id.itemId = :itemId and iv.id.itemTypeId = :itemTypeId ");
List<ItemView> result = (List<ItemView>)getEntityManager()
.createQuery(hql)
.setParameter("itemId", itemId)
.setParameter("itemTypeId", itemType.getId())
.setMaxResults(1)
.getResultList();
return result.isEmpty()
? null : result.get(0);
}
This dao method always returns empty results, never finding existing rows in the view??? I know those rows exist because when I do getAll() on the same dao I see results and I see a matching row for the criteria.
Is there anything special about selecting rows from a view in H2 database?
Thanks
Ok fixed, I had to use a smaller number for LOCK_TIMEOUT value, so now I can connect to database and see values. Selecting from view problem also fixed.
I have to say H2 is really neat and elegant. I'm glad, I switched the unit test db to H2.

Resources