Database: Criteria and native SQL query

1 Criteria query

       

In addition to providing powerful HQL queries, Hibernate also provides a query method called Criteria. HQL is very similar to SQL, which is characterized by flexibility and rich functions, but the disadvantage is that users must be familiar with the syntax of SQL, and when combining conditional queries, it is often necessary to assemble the Where condition and provide parameters for the condition. Criteria query is more object-oriented, better combined with Java code, and often more convenient when combining conditional queries. Of course, Criteria also has its disadvantages. Its readability is not as high as HQL, and its functions are not as many as HQL.

        Hibernate officials often recommend using HQL to solve problems.

1.1 How to use Criteria .

 

Criteria criteria = sess.createCriteria(Category.class); // Create the query object Criteria of the persistent class

        criteria.add( rule ); // Set query rule criterion

        List list = query.list(); // Get query results

 1.2 Rules - Criterion

Criterion is the query condition of Criteria. Criteria provides the add(Criterion criterion) method to add query conditions. The main implementations of the Criterion interface include: Example, Junction, and SimpleExpression. The actual use of Junction is its two subclasses, conjunction and disjunction, which use AND and OR operators to join query condition sets respectively.

Criterion instances can be provided through the Restrictions factory class, and Restrictions provides a large number of static methods, such as eq (equal), ge (greater than or equal to), between, etc. to create Criterion query conditions

(SimpleExpression instance). In addition, Restrictions also provides methods to create conjunction and

Disjunction instance, add query criteria to form a set of query criteria by adding (Criteria) method to the instance.

Static method conditions in Restrictions

meaning

Criteria

HQL

equal

Restrictions.eq()

=

not equal to

Restrictions.not(Exprission.eq())

<>

more than the

Restrictions.gt()

>

greater or equal to

Restrictions.ge()

>=

less than

Restrictions.lt()

<

less than or equal to

Restrictions.the()

<=

equal to empty

Restrictions.isnull()

is null

non empty

Restrictions.isNotNull()

is not null

fuzzy query

Restrictions.like()

like

logic and

Restrictions.and()

and

logic and

Restrictions.conjunction()

and

logical or

Restrictions.or()

or

logical or

Restrictions.disjunction()

or

logical NOT

Restrictions.not()

not

equal to a certain value

Restrictions.in()

in( )

not equal to any value

Restrictions.not(Restrictions.in())

not in()

interval

Restrictions.between()

between x and y

not in range

Restrictions.not(Restrictions..between())

not between x and y

(1) Add simple type attribute restrictions (query conditions) for Criteria.

        Criteria criteria = sess.createCriteria(Movie.class);

        criteria.add(Restrictions.like("title", "%%"));

        List<Movie> list = criteria.list();

(2) Add association class attribute restrictions for Criteria.

        Direct use of the add() method of criteria can only add simple type attribute restrictions and Id attribute restrictions for associated classes. If you want to add other attribute restrictions of the associated class (such as adding the name attribute restriction of the associated class Category for the Movie entity, you must re-createCriteria() and pass in the associated attribute name as a parameter, and then you can use the attribute of the associated class Category as the restriction condition .

        Criteria criteria = sess.createCriteria(Movie.class);

        criteria = criteria.createCriteria("category");                   // re-execute createCriteria()

        criteria.add(Restrictions.eq("name","动漫"));

        List<Movie> list = criteria.list();

        The above effects can also be achieved through the createAlias() method of criteria. Unlike createCriteria, it just gives an alias to the associated entity. After using createAlias, other attributes of the queried object can still be used as restrictions.

        List<Movie> list = sess.createCriteria(Movie.class)

                                                  .createAlias("category", "c")

                                                  .add(Restrictions.eq("c.name", "战争"))

                                                  .add(Restrictions.like("title", "%"))

                                                  .list();

 1.3 Use an entity to declare multiple restrictions on equal or like rules at once—Example

Example is also a way to add Criteria rules. This way uses an object of the query entity class to declare multiple rules in one go. The creation of Example is different. Example itself provides a static method create(Object entity), and the parameter is an entity object (usually a mapped entity object in actual use) to create. Then you can set some filter conditions:

        Example example = Example.create(entity)

                                                           .ignoreCase() // ignore case

                                                           .enableLike(MatchMode.ANYWHERE); // use like

        criteria.add(example);

        List list = criteria.list()

1.4 Implement sorting 

You can use Criteria's addOrder(Order order) to control the order of query results. The Order object instance can be obtained through Order.asc("property name") and Order.desc("property name").

        List cats = sess.createCriteria(Cat.class)

                                  .add( Restrictions.like("name", "F%")

                                  .addOrder( Order.asc("name") )

                                  .addOrder( Order.desc("age") )

                                  .list() ;

1.5  Realize pagination

The Criteria object, like the Query object, can implement pagination through the setFirstResult() and setMaxResults() methods

1.6  Projection Projection—implementing aggregation functions and grouping

Criteria can implement aggregation statistics and grouping through the setProjection(Projection projection) method.

Projection mainly enables Criteria to perform statistical queries and realize grouping. Projection is mainly realized by SimpleProjection and ProjectionList. The creation of SimpleProjection and ProjectionList is done through the built-in static method of Projections, such as the provided avg(), count(), max(), min(), sum() can make it easy for developers to set a certain field Perform statistical queries. The groupProperty() method of Projections can also group results.

        ProjectionList projectionList = Projections.projectionList();

        Projection prjCount = Projections.count("id");

        projectionList.add(prjCount);

        projectionList.add(Projections.groupProperty("category"));

        criteria.setProjection(projectionList);

        List<Object[]> list = criteria.list();

1.7 DetachedCriteria 

The DetachedCriteria class is similar to the Criteria interface. You can use the methods mentioned above (Criterion and Projection) to set the query conditions, but the creation methods of the two are different: the Criteria must be created by the Session object, and the DetachedCriteria does not need the Session object when it is created. Therefore, DetachedCriteria can be constructed outside the Session scope, and a series of complex conditions can be added, and then passed to the Dao method with the Session environment for execution. The emergence of DetachedCriteria realizes the separation of "conditional construction" and "query execution".

public static void main(String[] args) {
		DetachedCriteria cri = DetachedCriteria.forClass(Movie.class);
		cri.add(Restrictions.eq("category.id", 1));
		List<Movie> list = get(cri);
		for(Movie m: list){
			System.out.println(m.getTitle()+","+m.getCategory().getName());
		}
	}
	static List get(DetachedCriteria cri){
		Session sess = null;
		try {
			sess = HibernateUtil.getSession();	
			return cri.getExecutableCriteria(sess).list();
		} finally {
			if(sess!=null)
				sess.close();
		}
	}

2 Native SQL operations 

2.1 Native SQL query

Although HQL is powerful enough, because different database systems have different extensions to standard SQL (such as T-SQL of SQL Server, PL/SQL of Oracle, and dialect "Dialect" in Hibernate), HQL cannot be completed 100%. What we can achieve in native SQL. Moreover, HQL must eventually be converted to SQL for execution. This automatic conversion is always unsatisfactory. After converting overly complex HQL to SQL, the execution efficiency may be low. For this reason, Hibernate also reserves our right to directly use the local SQL of the database, and we can directly write SQL statements to control the query results. It is worth noting that once native SQL is used, if you switch to another database system for the data access layer in the future, you will need to modify these native SQL to conform to the new database dialect.

(1) A native SQL query that returns an array of primitive types Object.

The usage of local SQL query and HQL query is basically similar, the difference is that SQL query needs to use the createSQLQuery(String sql) method of Session, and the returned query object is of type SQLQuery.

String sql = "select m.Title, c.name from Movie m inner join Category c on m.CategoryId=c.Id where c.name=:cname";

SQLQuery query = sess.createSQLQuery(sql);

query.setString("cname", " war ");

List<Object[]> list = query.list();

(2) A native SQL query that directly returns the mapped entity.

We often hope to return persistent entity objects through local SQL queries. If the above method is used, the result returned by Hibernate is an array of basic types of Object. To obtain entities, it is necessary to rebuild entity objects and set properties. In order to simplify our work, the SQLQuery interface object directly provides the addEntity(String alias, Class entityClass) method, which can help us directly fill the SQL result into the entity object and return the entity object array and list.

String sql = "select m.*, c.* from Movie m inner join Category c on m.CategoryId=c.Id where c.name=:cname";
SQLQuery query = sess.createSQLQuery(sql);
query.addEntity("m",Movie.class);
query.addEntity("c",Category.class);
query.setString("cname", "战争");
List<Object[]> list = query.list();
for(Object[] arr : list){
        Category c = (Category)arr[1];
        Movie m = (Movie)arr[0];
        System.out.println( c.getName() + "," + m.getTitle());
}

2.2 Native JDBC operation 

If you want to use native JDBC to add, delete, and modify more flexibly, you can use the doWork method provided by the Session object to write an internal anonymous class through the Work interface. We can call the underlying API of JDBC to implement batch operations.

The Session.doWork() method is executed as shown below.

Session session=HibernateUtil.openSession();
	Transaction transaction=session.beginTransaction();
	session.doWork(new Work() {
			public void execute(Connection conn) throws SQLException {
				//这里是SQL非HQL
				String sql = "delete from Movie where categoryId=?"; 
				PreparedStatement stmt = conn.prepareStatement(sql);
				stmt.setInt(1, 2);
				stmt.executeUpdate();
			}
	});
	transaction.commit();

Guess you like

Origin blog.csdn.net/qq_55917018/article/details/128237954