University of Applied Sciences HTW Chur Master of Science in Engineering (MSE) Seminar Datenbanksysteme The LINQ-Approach in Java Student: Norman Süsstrunk Tutor: Martin Studer 18 th October 2010
Seminar Datenbanksysteme : The LINQ-Approach in Java 2 Abstract LINQ is a component in the.net framework that enables writing SQL-querys in the programming language itself. This approach became quite popular in.net and is seen as a big advantage over other popular programming languages like Java. The popularity of LINQ has led to a lot of research how LINQ could be implemented in Java. There exist several projects that try to implement the LINQ-Approach in Java. In this paper, there will be first a discussion what the key benefits of LINQ are. Next it presents two projects that enable some sort of LINQ-capability in Java. The frameworks will be analysed in its implementation and their capabilities. Approval Date/Signature Tutor: Date/Signature Student:
Seminar Datenbanksysteme : The LINQ-Approach in Java 3 Table of contents Abstract... 2 Approval... 2 1 Introduction to LINQ... 4 1.1 What is LINQ?... 4 1.2 The LINQ Providers... 4 1.3 LINQ Example... 5 1.4 Key benefits of LINQ... 5 2 Actual Implementations of LINQ for Java... 7 2.1 JaQU... 7 2.2 sbql4j... 11 3 Conclusion... 15 4 Bibliography... 16
Seminar Datenbanksysteme : The LINQ-Approach in Java 4 1 Introduction to LINQ 1.1 What is LINQ? LINQ is a component of the.net-framework and stands for Language Integrated Query. The syntax of LINQ is based on the commands of the SQL query language such as "select", "from" and "where". This enables writing query expression in the programming itself. LINQ offers the benefits of both compile time checking and simplified development of query expressions. LINQ provides almost all standart query operators such as Select Where SelectMany Sum / Min / Max / Average Aggregate Join / GroupJoin and many more LINQ can be used to query all sort of data structures is not limited to relational databases like MS SQL Server or MySQL. This is enabled by the LINQ providers wich are presented in the next section. 1.2 The LINQ Providers A LINQ query retrieves data from a data source. In.NET, any type implementing IEnumerable or IEnumerable<T> is a valid source of data and is known as a queryable type. We can define our own custom types implementing IEnumerable<T>, and LINQ will work on our custom types with no additional modifications. A LINQ provider can be descriped as a connector for LINQ to query data that is not inside a queryable type. With LINQ providers, it is possible to query data inside almost any database server (SQL Server, MySQL etc.), inside XML, inside XSD, inside Twitter, inside Google, etc.
Seminar Datenbanksysteme : The LINQ-Approach in Java 5 1.3 LINQ Example Listing 1 is an example written in C# showing the key features of LINQ: public void printsoldoutproducts() { List<Product> products = GetProductList(); var soldoutproducts = from p in products where p.unitsinstock == 0 select p; Console.WriteLine("Sold out products:"); foreach (var product in soldoutproducts { Console.WriteLine("{0 is sold out!", product.productname); Listing 1 : A simple query in LINQ Listing 1 shows how a query is expressed with LINQ. The query filters out all products wich aren t in stock anymore. If we translate this LINQ expression in a SQL query, the query would look like this: SELECT * FROM PRODUCTS P WHERE P.UNITS_IN_STOCK = 0 1.4 Key benefits of LINQ Listing 1 shows a typical implementation of an execution of a simple SQL query in a modern programming language. The example is written in Java. try { Statement stmt = connection.createstatement(); String sql = "SELECT * FROM PRODUCTS P WHERE P.UNITS_IN_STOCK = 0"; stmt.executeupdate(sql); catch (SQLException e) { //... Listing 2 : typical way to execute an sql query in a programming language. The code shown here is written in Java The SQL-statement is typically stored in a string variable. Then the query will be executed on the connection to the database. This implementation has the following drawbacks:
Seminar Datenbanksysteme : The LINQ-Approach in Java 6 We have to assure that the query will be syntactically correct. The compiler of the programming language can t detect wrong querys as they are embedded in strings. There is no way to refactor the query with a refactoring tool. For example, if we modify the relational model with a refactoring tool, the tool can t consider querys that are stored in strings and are concerned to the change of the relational model. SQL querys only work with relational databases. We can t express a query for an array in Java. In.NET and its LINQ-feature, querys are an integral part of the language. This has the following advantages: The compiler checks the syntax of queries at compile time. No syntactically wrong query will execute on a database. If the queried data structures change, the query expression will be checked if it is still valid. For example, if some tables in a database change its structure, the querys can be checked if they still work with the altered table structure. In an integrated development environment (IDE), writing querys will be simplified because the IDE can autocomplete the query and thus writing querys can be much faster. An IDE can automatically refactor a query if for example the classes involved in the query are being refactored. Mapping to domain objects is done by LINQ Possibility to debug a query in the IDE. That s not possible with a query stored in a string. The querys can be optimized by the LINQ-providers.
Seminar Datenbanksysteme : The LINQ-Approach in Java 7 2 Actual Implementations of LINQ for Java The popularity of LINQ has led to attempts integrating LINQ in other programming languages. Such projects exists for Java, PHP, Javascript and others. Most of the projects try to simulate LINQ with their existing language components. To really enable the feautures of LINQ in a programming language, the programming language itself has to be extended. We have seen in the LINQ example in.net at the beginning, that expressing querys is an integrated part of the programmin language itself. There are ongoing discussions in the Internet to integrate LINQ into the Java programming language[6]. By now, it seems that there are no plans to integrate LINQ in Java. At this time, no Java language request (JSR) concerning LINQ can be found. In the next sections, there will be presented two projects for the Java language wich try to simulate writing integrated querys. They work with two different approaches. The projects where analyzed by the following aspects: How a query can be expressed The actual implementation Usability of the frameworks. 2.1 JaQU JaQU is a subproject of the developer of the popular H2 database engine and stands for Java Query. In listing 3, we see how the LINQ query from the beginning example is written with JaQU: Product p = new Product(); List<Product> soldoutproducts = db.from(p).where(p.unitsinstock).is(0).select(); Listing 3 : The query from listing 1 implemented with JaQU The class Product is a model class that maps to to a table Product in a H2 database. The reference db holds a connection to the H2 database. The statement in Listing 3 stands for the following SQL query: SELECT * FROM PRODUCTS P WHERE P.UNITS_IN_STOCK = 0 Listing 4 : The sql representation of the statement in listing 3 It can be see that the query is composed with method calls. So the query isn t expressed with keywords as this can be done in C# with LINQ. A lot of the key advantages that where stated for LINQ also can be seen here. Querys are expressed in a natural and object-oriented way.
Seminar Datenbanksysteme : The LINQ-Approach in Java 8 The query statements are easy to write with auto completion Code can be refactored It s type save because the API is strongly based on generics. Implementation of JaQU Running the example in listing 3 results in the following steps inside the JaQU-framework: 1. Creating and mapping the table to the model class In the example in listing 3, the query is performed on a list with objects of the type Product. The class Product will be inspected to create a SQL query that creates a table with the name Person. The columns of the table are based on the fields of the class Person. Listing 5 shows the field definitions of the class Product. Listing 6 shows the resulting SQL query that creates the table Product. public class Product implements Table { // public Integer productid; public String productname; public String category; public Double unitprice; public Integer unitsinstock; Listing 5 : Field definitions of the class Products CREATE TABLE IF NOT EXISTS Product ( productid INT, productname VARCHAR, category VARCHAR(255), unitprice DOUBLE, unitsinstock INT, PRIMARY KEY(productId) ) Listing 6 : Query to create the table for the class Product The framework then stores the relation of the model classes to its corresponding tables in a internal hashmap.
Seminar Datenbanksysteme : The LINQ-Approach in Java 9 2. Creating the SQL query The SQL query now will be composed based on the method calls where(..).is(..).select(). The query is being constructed step by step, the result is a string holding the complete query. Listing 7 shows that the query will be constructed with strings representing parts of a SQL query. SQLStatement prepare(sqlstatement selectlist, boolean distinct) { SQLStatement stat = selectlist; String selectsql = stat.getsql(); stat.setsql(""); stat.appendsql("select "); if (distinct) { stat.appendsql("distinct "); stat.appendsql(selectsql); stat.appendsql(" FROM "); from.appendsql(stat); for (SelectTable join : joins) { join.appendsqlasjoin(stat, this); appendwhere(stat); if (groupbyexpressions!= null) { stat.appendsql(" GROUP BY "); int i = 0; for (Object obj : groupbyexpressions) { if (i++ > 0) { stat.appendsql(", "); appendsql(stat, obj); stat.appendsql(" "); if (!orderbylist.isempty()) { stat.appendsql(" ORDER BY "); int i = 0; for (OrderExpression o : orderbylist) { if (i++ > 0) { stat.appendsql(", "); o.appendsql(stat); stat.appendsql(" ");
Seminar Datenbanksysteme : The LINQ-Approach in Java 10 return stat; Listing 7 : Method to construct the query string The documentation of JaQU states that JaQU is testet with the H2 database but it should work with every database that supports JDBC. We can see above that JaQU translates the query expressed by the method calls into SQL querys stored in strings. That limits the use of JaQU to classic databases. Querying collections like arrays or lists isn t possible with that approach. As a conclusion we can say that JaQU just simplifies the generation of SQL querys. The code that tests the framework shows that almost all kinds of querys can be realized. Querys with joins and complex conditions are demonstrated and seem to work flawlessly.
Seminar Datenbanksysteme : The LINQ-Approach in Java 11 2.2 sbql4j SBQL4J is another framework that enables to express a query in the same way like LINQ. SBQL4J basically works with a preprocessor that parses the querys and translates them into Java code. Here s our example from the beginning written for sbql4j: /** * This sample uses where to find all products that are out of stock. */ public void linq2() { List<Product> products = getproductlist(); List<Product> soldoutproducts = #{ products where unitsinstock == 0 ; System.out.println("Sold out products:"); for(product product : soldoutproducts) { System.out.printf ("%s is sold out!\n", product.productname); Listing 8 : The query from listing 1 implemented with sbql4j This code can t be compiled with a java compiler as it uses the keyword where that isn t a part of the java programming language. SBQL4J is implemented based on the theory of the so-called stacked based query language (SBQL). The conceptual architecture of SBQL involves the following elements: 1 1. integrated development environment (IDE) for preparing source SBQL programs. 2. a parser which generates a query syntax tree 3. an interpreter which recursively traverses a syntax tree producing the result of a query or of a program. To make such an expression work with sbql4j, the following steps are needed: 1. All the the code that contain integrated querys must be written in a specific file format with the ending.s4j. As we can see in the figure 1 http://sbql.pl/overview/#t01
Seminar Datenbanksysteme : The LINQ-Approach in Java 12 below, not even syntax highlighting works in a typical java ide like eclipse. It s obvious that either autocompletion nor check of the code by the compiler is done while writing the code in the ide. 2. After the code is written, a ant task has to be run that calls the API to perform the preprocessing of the.s4j-files and finally generates java code wich can be used in further client code.
Seminar Datenbanksysteme : The LINQ-Approach in Java 13 In Listing 9, we can see the generated code from Listing 8. The query was translated in a loop where every product from the productlist is analyzed of the demanded properties that originate from the where-condition in the query. public class LinqComparison_SbqlQuery1 { private List< Product> products; public LinqComparison_SbqlQuery1(List< Product> products) { this.products = products; // query='products where unitsinstock == 0' public List<Product> executequery() { List<Product> _queryresult = new ArrayList<Product>(); int _whereloopindex = 0; for (Product _whereel : products) { Boolean _equalsresult = OperatorUtils.equalsSafe (_whereel.unitsinstock, 0); if (_equalsresult) { _queryresult.add(_whereel); _whereloopindex++; return _queryresult; Listing 9 : Generated code after preprocessing through sbql4j
Seminar Datenbanksysteme : The LINQ-Approach in Java 14 What happens if we write a query that is syntactilly correct but has a condition on a property that doesn t exist? In listing 10, a second condition on the fictional property test is added to our integrated query. public void linq2() { List<Product> products = getproductlist(); List<Product> soldoutproducts = #{ ; products where unitsinstock == 0 and test = 0 System.out.println("Sold out products:"); for(product product : soldoutproducts) { System.out.printf ("%s is sold out!\n", product.productname); Listing 10 : query that references a field that doesn t exist After running ant, the following outputs in the console [sbql_pre] LinqComparison.s4j:152: Name test cannot be resolved [sbql_pre] where unitsinstock == 0 and test == 0 It recognizes that the field test in the model class Product doesn t exists. Querys that are syntactically wrong are also detected.
Seminar Datenbanksysteme : The LINQ-Approach in Java 15 3 Conclusion The popularity of LINQ is no surprise. LINQ enables the expression of queries for any data structures integrated in the language. Because LINQ is an integrated part of the language, the compiler can detect errors in querys and tools for generating and refactoring of queries can be used. This was previously not possible with querys stored in strings. The two projects SBQL4j and JaQU show how one can express querys similar to LINQ in Java. The underlying concepts, however, limit the application of the frameworks. JaQU just generates querys for classic databases and doesn t work with other datastructures. SBQL4J enables real language integrated querys. But it requires its own file format and the code must be preprocessed. The fileformat isn t supportet by java development tools so writing querys isn t that fluent like in.net. LINQ in Java only becomes real if it the java language will be extended. It remains to be seen if Sun will pick up LINQ as a language feature in Java und how it will be implemented.
Seminar Datenbanksysteme : The LINQ-Approach in Java 16 4 Bibliography [1] www.odbms.org. LINQ is the best option for a future Java query API. 2010 йил 1-12. http://www.odbms.org/blog/2008/08/linq-is-best-optionfor-future-java (accessed 2010 йил 21-09). [2] Wikipedia. LINQ - Wikipedia. http://de.wikipedia.org/wiki/linq (accessed 2010 йил 21-10). [3] Albahari, Joseph, and Ben Albahari. LINQ Pocket Reference. O'Reilly Media, 2008. [4] JaQu. JaQu. http://h2database.com/html/jaqu.html (accessed 2010 йил 21-10). [5] sbql.pl. Stack-Based Architecture (SBA) and Stack-Based Query Language (SBQL). 12 2010. http://sbql.pl/overview/ (accessed 12 2010). [6] stackoverflow. Discussion "LINQ for Java tool". http://stackoverflow.com/questions/346721/linq-for-java-tool (accessed 2010 йил 21-10).