Querydsl nested query generated an error sql - sql

I wrote a simple nested query
#Autowired
#PersistenceContext
EntityManager entityManager;
#Autowired
Configuration configuration;
private JPASQLQuery<?> queryFactory;
#PostConstruct
public void init() {
queryFactory = new JPASQLQuery<>(entityManager, configuration);
}
public void student() {
QStudent student = new QStudent("student");
QStudent nested = new QStudent("nested");
List<?> fetch = queryFactory.select(student.id)
.from(SQLExpressions.select(nested.id)
.from(nested), student)
.fetch();
}
The entity structure is like this
#Entity
#Table(name = "u_student")
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
The generated sql is like this
select student.id
from u_student (select nested.id
from u_student nested) as student
Outside sql added a tableName up, causing sql syntax error
Am I wrong? How should such a nested query be written?
The first time you send a question is not very useful, thank you.

Found that using PathBuilder can solve this problem
The complete code is:
PathBuilder<Tuple> studentAlias = new PathBuilder<>(Tuple.class,"student");
QStudent student = new QStudent("student");
QStudent nested = new QStudent("nested");
List<?> fetch = queryFactory.select(student)
.from(SQLExpressions.select(nested.id)
.from(nested), studentAlias)
.fetch();
Generated sql:
select student.id as id1_90_0_
from (select nested.id from u_student nested) as student
Do you have any better plans?

Related

Query for oneToMany relationship

I am looking for solve my issue.
I have something like this.
class A{
#OneToMany(mappedBy="a")
private List<B> bs;
}
class B {
#ManyToOne
private A a;
private String name;
#Lob
private byte[] img;
}
I want get all records from database except img field from relationship B.
Maybe create query in JPA but how do this correct?
How can I do that?
You could define img as lazy:
#Basic(fetch=FetchType.LAZY)
#Lob
private byte[] img;
That way the image is only loaded when you access the getter.
Second option is to create a DTO (Data transfer object) using the constructor expression:
package dto;
public class BDto {
private final String name;
private final A a;
public BDto(String name, A a) {
this.name = name;
this.a = a;
}
// getters for both fields
}
Then you can create a query like:
select new dto.BDto(b.name, b.a) from B b where b.a.received = true
Important notice: the dto must be used in the query fully qualified (e.g. dto.BDto)

Error in insert statement for HSQL DB

I have Spring data rest application & for unit testing these services, I am using Spring Boot & HSQL in memory databse. But while inserting data into the HSQL table at runtime, I am getting an error. While other insert statements are working, I am getting this error only for 1 insert statement.
Error
Caused by: java.sql.SQLException: Column count does not match in statement
Insert Statement in SQL file
Insert into countries (ID,COUNTRY,CODE) values (2,'UNITED STATES','US');
Note:- In the same application insert for other tables are working & retrieval of the data from the table is also successful.
Entity - Using this HSQL create the table.
#Entity
#Table(name = "COUNTRIES")
public class Country implements Describable, Serializable {
#Id
#SequenceGenerator(name="CountriesSeq",sequenceName="SEQ_COUNTRIES")
#GeneratedValue(strategy = GenerationType.AUTO, generator = "CountriesSeq")
protected Integer id;
#Column(name = "CODE")
private String code;
#Column(name = "COUNTRY")
private String country;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
Thanks
This issue is resolved. The table had trigger on it which I didnt notice. Thanks for your input Acewin.

how can i get "one" OBJECT from "many" OBJECT in ManyToOne relationship? please help me?

this is my java code :three entity including CompanyTypeRelation ,CompanyType,Department
public class CompanyTypeRelation implements java.io.Serializable {
private static final long serialVersionUID = 4227115995926533087L;
// Fields
private long id;
private CompanyType companyType;
private Department department;
private long operator;
private String operateTime;
// the relationship
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="company_type_id", nullable=false)
public CompanyType getCompanyType() {
return this.companyType;
}
public void setCompanyType(CompanyType companyType) {
this.companyType = companyType;
}
// the relationship
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="company_id", nullable=false)
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
..............
other code:
}
this is my query sql :
SELECT c
FROM com.hna.dt.orm.CompanyTypeRelation c
LEFT JOIN c.companyType ct LEFT JOIN c.department cd
can I get departmentName from Department by the sql above?
assuming that the departmentName is in the department table, just add cd.name (or whatever the column name is) to your select list.

Problems with ActiveRecord and LINQ queries

I have a simple class:
public class User : ActiveRecordLinqBase<User>
{
[PrimaryKey(Column = "user_id", Length = 20)]
public string Id { get; set; }
[Property(Column = "password", Length = 16)]
public string Password { get; set; }
...
}
and I have created the following repository:
public class SqlRepository<T> : IRepository<T> where T : ActiveRecordLinqBase<T>, new() {
public void Add(T entity) {
entity.SaveAndFlush();
}
public void Remove(T entity) {
entity.DeleteAndFlush();
}
public void Modify(T entity) {
entity.UpdateAndFlush(); ;
}
...
public IEnumerable<T> FindAll(Func<T, bool> predicate) {
return ActiveRecordLinqBase<T>.Queryable.Where(predicate);
}
}
Now, when running the following unit test (against a MySQL database):
[Test]
public void Test_Sample() {
var repo = new SqlRepository<T>();
repo.Add("john.doe", "keyword1");
repo.Add("other.user", "keyword2");
var users = repo.FindAll(x => x.Username.Contains("john")).ToList();
Assert.AreEqual(1, users.Count);
}
... I get the following SQL query:
SELECT this_.user_id as user1_0_0_, this_.password as password0_0_, this_.role as role0_0_ FROM users this_
Where is the WHERE clause?
If I instead do the following in the same test directly...
var users = User.Queryable.Where(x => x.Username.Contains("john"));
I get the following SQL:
SELECT this_.user_id as user1_0_0_, this_.password as password0_0_, this_.role as role0_0_ FROM users this_ WHERE this_.user_id like ?p0;?p0 = '%john%'
Am I doing something wrong?
What is the difference between those two queries?
Edit: I also tried with
return ActiveRecordLinq.AsQueryable<T>().Where(predicate);
without success.
Now this is just because I like code, and sometimes I notice stuff... I'm no expert on Active Record, so this is just a guess...
Maybe you should change the signature of the FindAll method from
public IEnumerable<T> FindAll(Func<T, bool> predicate)
into
public IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate)
which will allow you to hit the right overload of Where, which is most likely the overload you're looking for.
It's because a Func can't be reflected upon the same way an Expression of Func can.

Delete one row from the database

I'm having a problem deleting just one row. I can insert and delete the whole table. I'm not able to understand the whole ID thing in order to delete just one row. I was looking at some examples, but I couldn't get it. It’s driving me crazy.
Here is the SQLite class;
public class datahelper {
private static final String DATABASE_NAME = "table.db";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "table1";
private Context context;
private SQLiteDatabase db;
private SQLiteStatement insertStmt;
private static final String INSERT =
"insert into " + TABLE_NAME + "(name) values (?)";
public datahelper(Context context) {
this.context = context;
OpenHelper openHelper = new OpenHelper(this.context);
this.db = openHelper.getWritableDatabase();
this.insertStmt = this.db.compileStatement(INSERT);
}
public long insert(String name) {
this.insertStmt.bindString(1, name);
return this.insertStmt.executeInsert();
}
public long insert2(String name) {
this.insertStmt2.bindString(1, name);
return this.insertStmt2.executeInsert();
}
public void deleteAll() {
this.db.delete(TABLE_NAME, null, null);
}
private static class OpenHelper extends SQLiteOpenHelper {
OpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME +
" (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)");
}
}
Execute the query
DELETE FROM TABLE_NAME WHERE id = SOMEVALUE
It looks like you are using this API, which provides this delete method. My guess is that you would do this:
public void delete(int id) {
this.db.delete(TABLE_NAME, 'id = ?', new String[] { id.toString() });
}
(Original answer...)
Use a DELETE statement with a WHERE clause that deletes only the row with the id you want to remove:
DELETE FROM <tablename> WHERE id = ?
Of course, you need to know the id in order to do this. SQLite provides a function — sqlite3_last_insert_rowid() — that you can call immediately after an INSERT. If your API doesn't provide this function directly, you can get it indirectly via the equivalent SQL function:
SELECT last_insert_rowid()
Alernatively if you want to delete a certain name (assuming it's unique):
DELETE FROM <tablename> WHERE name = ?