I have a table with columns as rows.
Now I want to apply restriction on multiple rows with "and" condition.how can we do this using hibernate criteria?
Example: Employee table
Pk ColumnName. Value
------------------------
1. Empid. 10
1 EmpName. Sachin
1. Empsalary. 10,000
2 Empid. 20
2 EmpName. Dhoni
2. Empsalary. 8000
Now I want to fetch pk's which have EmpName as sachin and empsal as 10,000
So it should return pk as 1.
Please check image attached
You can fetch the primary key list of data from DB using criteria query. Follow the below code snippet:
EntityManager enm = sessFact.createEntityManager();
CriteriaBuilder en = sessFact.getCriteriaBuilder();
CriteriaQuery<Integer> qu = en.createQuery(Integer.class);
Root<Employee> ro = qu.from(Employee.class);
qu.select(ro.get("id"));
qu.where(en.like(ro.get("empName"), "Sachin%"), en.equal(ro.get("empSalary"), 10000 ));
List<Integer> list= enm.createQuery(qu).getResultList();
for (Integer name : list) {
System.out.println("PK: " + name);
}
in the where clause you can remove the "%" and give the exact search e.g., qu.where(en.like(ro.get("empName"), "Sachin"), en.equal(ro.get("empSalary"), 10000 ));
The equivalent SQL log generated by hibernate is in below:
Hibernate: select employee0_.id as col_0_0_ from employee employee0_ where (employee0_.emp_name like ?) and employee0_.emp_salary=10000
FYI, The referred DB Table structure is as in below:
CREATE TABLE employee (
id int(11) NOT NULL AUTO_INCREMENT,
emp_name varchar(100) DEFAULT NULL,
emp_address varchar(500) DEFAULT NULL,
emp_mobile_nos varchar(100) DEFAULT NULL,
emp_salary int(12) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Please find the complete code related to Hibernate in GIT here - https://github.com/ctmithun/HibernateExample/blob/master/Hibernate5Annotation/src/net/roseindia/GetAllData.java
Related
I have a products table that contains especially a product_name and a product_type.
For certain product types, I'd like to create some kind of overlay mapping table that replaces the value in product_name.
In pure mysql, I would solve this as follows:
CREATE TABLE products (
id int NOT NULL AUTO_INCREMENT,
product_type varchar(20) NOT NULL,
product_name varchar(255) NOT NULL,
product_price;
product_quantity;
...
)
#Entity
public class Product {
long id;
String product_type;
String product_name;
String product_price;
...
}
CREATE TABLE product_mapping (
id int NOT NULL AUTO_INCREMENT,
product_type varchar(20) NOT NULL,
product_name varchar(255) NOT NULL,
PRIMARY KEY (id)
);
My goal: if product_mapping contains the product_type, override the product_name. Else, stick to the value in products.product_name table.
SELECT ..., ifnull(product_mapping.product_name, products.product_name) AS product_name
FROM products
LEFT JOIN product_mapping ON products.product_type = product_mapping.product_type;
But how could I create the same mapping with a hibernate #Entity
Sidenote: A #Formula creates an additional SELECT for each query, whose result is merged into the #Entity. I'm looking for a JOIN!
I am working on java with JDBC connections and trying to perform DDL commands.
Here i had a doubt about one particular flow, can that be possible? if yes, can you explain me how and what to do with example.
I am trying to select data from item table containing item_id, sale_price, description, barcode columns and want to update barcode data for item_id = 9 and insert into item_duplicate table. With out updating the item table. But item_dupliacte table should contain the updated value for barcode.
my item_duplicate table
item table
MERGE item_duplicate AS D
USING item AS I
ON (D.item_id = I.item_id )
WHEN MATCHED
THEN UPDATE set D.part_no='new part'
WHEN NOT MATCHED BY D
THEN
INSERT (item_id,part_no,sale_price,description,barcode)
SELECT i.ITEM_ID,i.PART_NO,i.SALE_PRICE,i.DESCRIPTION,b.BARCODE
FROM item i
JOIN item_barcode b
ON b.ITEM_ID = i.ITEM_ID
WHERE i.ITEM_ID = ?
WHEN NOT MATCHED BY I
THEN DELETE;
A simple insert into select from.
CREATE TABLE dbo.TEST
(
item_id INT NOT NULL
, barcode VARCHAR (20) NULL
, sale_price DECIMAL (14, 2) NULL
, description VARCHAR (100) NULL
, PRIMARY KEY (item_id)
)
CREATE TABLE dbo.TEST_COPY
(
item_id INT NOT NULL
, barcode VARCHAR (20) NULL
, sale_price DECIMAL (14, 2) NULL
, description VARCHAR (100) NULL
, PRIMARY KEY (item_id)
)
INSERT INTO TEST_COPY (item_id, barcode, sale_price, description) SELECT item_id, '9999' as barcode, sale_price, description FROM TEST WHERE item_id = 9
Update 2
Query:
select distinct p.name, u.cookie_id
from product p
left join user_product up on p.id = up.product_id
left join user u on up.user_id = u.id
where p.active = true
and
(
u.cookie_id = '4c2fe5b2-73fe-4b28-baa6-23db0512114c'
or
not (exists (
select p1.id
from user_product up1, product p1
where p1.id = up1.product_id
))
)
Output:
how should be:
Update 1
I wrote the code with the use of stream() for the better understanding of the problem:
List<Product> productList = productRepository.findAllByActiveTrue();
productList = productList.stream().map(item -> {
if(item.getUserProducts() == null) return item;
List<UserProduct> userProductList = new ArrayList<>();
for (UserProduct userProduct : item.getUserProducts()) {
if(userProduct.getUser().getCookieId().equals(cookieId)){
userProductList.add(userProduct);
}
}
item.setUserProducts(userProductList);
return item;
}).collect(Collectors.toList());
I would like to know how correctly select data from the tables. I want to get all products.
But to get all products is easy. I also need to include in the output data (UserProducts and User) if there's a connection between Product and User by CookieId. In other words, I want to show all products with User and UserProducts (if possible) and exclude the relation Product-UserProduct-User if User's cookieId doesn't match the cookieId from the query.
I am trying the following query, but it returns me only products that has the connection between User and the product, not all products.
#Query("from Product pr join fetch pr.userProducts up left join fetch up.user u where pr.active = true and u.cookieId = :cookieId")
List<Product> getAllProductsByCookieId(UUID cookieId);
My database looks like this:
Visualisation of the idea:
SQL-queries to generate tables:
product-table
create table if not exists product
(
id bigint auto_increment
primary key,
active bit not null,
image_path varchar(255) null,
name varchar(255) null,
price double not null,
unit_number double null,
unit_type varchar(255) null
);
userProduct-table
create table if not exists user_product
(
quantity int null,
product_id bigint not null,
user_id bigint not null,
primary key (product_id, user_id),
constraint FKnw43wab2rt35jmofmpbhkibco
foreign key (product_id) references product (id),
constraint FKq5o2e33vlwpfc2k1mredtia6p
foreign key (user_id) references user (id)
);
user-table
create table if not exists user
(
id bigint auto_increment
primary key,
cookie_id varchar(255) null
);
Your requirement is not possible without scaler objects in JPA. i.e JPA cannot give you a Product object where p.getUserProducts() contains only some UserProducts.
See my answer here. Why left join on CriteriaQuery doesn't filter results?
or here problems with OneToMany including a filter clause in spring jpa
You have to use the native query option or any other option where you retrieve the columns and provide a mapper as to how to create the object. You can use the following sql query.
select p.product, u.cookie_id
from product p
left join user_product up on p.id = up.product_id
left join user u on up.user_id = u.id and u.cookie_id = '?1'
where p.active = true
group by p.product, u.cookie_id
I'm trying to use ActiveJDBC with HSQLDB:
Users.sql
CREATE TABLE users (
"ID" INTEGER GENERATED BY DEFAULT AS SEQUENCE seq NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR(100) NOT NULL,
LAST_NAME VARCHAR(100) NOT NULL
);
User.java
#IdName("ID")
public class User extends Model {....}
Main.java
User u = new User();
u.setFirstName("first_name");
u.setLastName("last_name");
u.save();
And when I try to save new row I have the following exception:
org.javalite.activejdbc.DBException: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: id, Query: INSERT INTO users (first_name, last_name) VALUES (?, ?), params: first_name,last_name
I think that problem in lower case in insert query. How I can fix this problem?
After googling for this HSQL exception message, I threw this code together that actually works. It uses ActiveJDBC, works with plain query and also works with instrumented model:
Base.open("org.hsqldb.jdbc.JDBCDriver", "jdbc:hsqldb:file:./target/tmp/hsql-test", "sa", "");
String create = "CREATE TABLE people (\n" +
" ID INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL,\n" +
" FIRST_NAME VARCHAR(100) NOT NULL,\n" +
" LAST_NAME VARCHAR(100) NOT NULL\n" +
");";
Base.exec(create);
Base.exec("INSERT INTO people (first_name, last_name) VALUES (?, ?)", "John", "Doe");
System.out.println("===>" + Base.findAll("select * from people"));
Person p = new Person();
p.set("first_name", "Jane", "last_name", "Doe").saveIt();
System.out.println(Base.findAll("select * from people"));
System.out.println(Person.findAll());
Base.close();
As you can see, the code that creates a table is a bit different, especially around the ID column.
The model looks like this:
#IdName("ID")
public class Person extends Model {}
Basically, you had the following issues with your code:
Definition of ID column with double quotes
ID column needs to be defined as IDENTITY (do not hold my feet to the fire, I'm no HSQL expert, but t works)
The model needs to overwrite the #IdName("ID"), since ActiveJDBC defaults to lower case id, unless you change that in the table (why not?)
Keep in mind, that some things may not work, since HSQL is not on a list of supported databases.
I hope this helps!
CREATE TABLE users (
ID INTEGER GENERATED BY DEFAULT AS SEQUENCE seq NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR(100) NOT NULL,
LAST_NAME VARCHAR(100) NOT NULL
);
Say I have this table
CREATE TABLE person(
person_id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
x_cordinates INT,
y_cordinates INT
);
In the past I have used
Person person = EntityManager.find(Person.class, primaryKey);
But the primary key in this instance is auto incremented, is it possible to get a row back using the other colums such as first_name and last_name to get the primary key along with the other values ?
You can create a NamedQuerry like that :
#NamedQuery(name="person.findAll", query="SELECT p FROM Person p WHERE like :first_name")
And can assign a value to "first_name" like that :
query.setParamter("fist_name", "%name%");
You can read this documentation.
Use method createQuery or createNativeQuery of entityManager.
With createQuery you have to use JPQL syntax and with createNativeQuery, you've to use the standard SQL syntax.
For example :
Query query = EntityManager.createQuery("select * from person p where p.first_name = :fname");
17.
query.setParameter("fname", firstName);
Person p = query.getSingleResult();