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
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)
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.
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.
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.
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 = ?