l17 data source layer

67
HÖNNUN OG SMÍÐI HUGBÚNAÐAR 2015 L17 Data Source Layer

Upload: olafur-andri-ragnarsson

Post on 16-Apr-2017

482 views

Category:

Software


1 download

TRANSCRIPT

HÖNNUN OG SMÍÐI HUGBÚNAÐAR 2015L17 Data Source Layer

Agenda

Design ObjectivesObject-Relational Impedance MismatchProblems with database programmingData Source PatternsSpring JDBCRU Data Framework Content Example

Reading

Object-relational impedance mismatchData Source Pattern• Data Transfer Object• Row Data Gateway• Table Data Gateway• Active Record• Data Mapper• Record set

Design Objectives

The Three Layers▪ Presentation– User’s interface to the system– User can be another system– Accepts input, displays views▪ Domain– The Application of the system– The “Business logic”– Has the tendency to creep into presentation and data source▪ Data Source– Connection to the database

We are dealing with relational databases• Wide-spread and well understood• SQL based, transactionally safe• These are important in enterprise softwareDrawbacks• Bottleneck in a modern Internet system• Impedance MismatchAlternatives• NoSQL databases• Object-Relational Mappers (ORM)

Relational Databases

Programs need to interface the Data Source• Usually this means relational databasesDatabase vendors usually supply drivers for databaseRational databases use SQL language• Fairly standard

Connecting to Data Sources

Databaseclasses Driver DatabsaseProgram

Objectives

▪ Hide SQL from the Domain Layer▪ Access to database needs to ensure– Speed and data integrity– Concurrent access of many clients▪ Database independence– It can be an objective to keep the system independent of particular

database technology▪ Data Source Layer needs to be maintainable– Database will change

Impedance Mismatch

Object Oriented world

classes, interfaces,

encapsulation, inheritance,

polymorphism

Relational Database world

Tables, view, primary keys, foreign keys,

stored procedures

Object-Relational impedance mismatch

Mapping Objects to Tables▪ Object Relational Impedance Mismatch▪ Objects are different than tables– Encapsulation, Accessibility, Interfaces, classes, inheritance▪ Data types are different– Booleans, dates, string etc.▪ Structural differences– Classes contain other classes

The Legacy Problem▪ In most cases the data model exists– The schema already exists– We cannot assume that we create the schema▪ Data tends to stick where it lends– Cannot assume that our application controls the schema– The schema will likely outlive the application

The Usability Problem▪ The Database API determines the usability of the data access– Should be easy to use▪ The programming model is important– Does matter how efficient and good a persistence framework is, if it

is complex and cumbersome to use▪ Tools may help, but should not be used to conceal excessive

complexity– If tools are required to generate data access the programming

model is likely to be complex

Using Databases▪ Programmers tend to want to solve all problems in their domain– Should we solve all problems in our object domain?– Should we write everything in Java or C#?▪ Databases are good at what they do– But it’s necessary to let them do it in a natural way

Database Code▪ Database programming can be very repetitive– Opportunities for reusability– JDBC is pretty low-level▪ Too much similar code is bad!– Don’t write code unless you have to– Try to write code for the business layer▪ Persistence Frameworks are difficult to build– Use the frameworks that exist– Examples: Spring JBDC, Hibernate, JPA, NHibernate, iBatis

https://en.wikipedia.org/wiki/List_of_object-relational_mapping_software

Whichofthesestatementsisfalse

A) Datatendstostickwhereitlends B) Databaseprogrammingtendstobelow-level C) Objectstendtomapnicelytothedatabase D) Databaseprogrammingtendstoberepetitive

QUIZ

Data Source Patterns

Domain Layer Patterns Recap▪ Transaction Script– Organises business logic by procedures where each procedure

handles a single request from the presentation▪ Domain Model– An object model of the domain that incorporates both behaviour

and data▪ Table Module– A single instance that handles the business logic for all rows in a

database table or view

Good Design▪ Separate database code from other code– Provide database classes to access the database– All SQL code in the same place– Factories for each database– Use of Connection Pools▪ Error handling– SQLException is isolated in the Data Source Layer– Wrap in domain specific exceptions – use of runtime exceptions

Design Example▪ Domain Model uses gateways

Useful Patterns▪ Data Transfer Object– An object that carries data between processes in order to deduce

the number of method calls▪ Record Set– An in-memory representation of tabular data

Data Transfer ObjectAn object that carries data between processes in order to deduce the

number of method calls

▪ Object that is used to transfer data between layers– Data Source returns data objects to web layer

Data Transfer Object▪ How it Works– Similar to Value Object but is constructed to carry data between

layers– Data source layer creates DTO for transfer– DTOs holds data – get/set method– Can be mutable or immutable– Could have methods to transform data – for example serialize the

data or convert to XML– Simple Domain Objects can be used as DTO• Creates dependencies

Data Transfer Object▪ Assembling DTO from domain objects– Assembler reduces dependencies

▪ When To Use It– Whenever you need to transfer multiple items of data between two

processes in a single method call

Record Set▪ An in-memory representation of tabular data

▪ How It Works– Contains the result of a database query– Common in ADO.NET and JDBC– One record is current, clients can traverse the set– Usually provided by the database code▪ When to Use It– When returning data from a query

Data Source Patterns▪ Table Data Gateway– Acts as a Gateway to a database table▪ Row Data Gateway– Acts as a Gateway to a single record in a data source▪ Active Record– Wraps a row in a database table or view, encapsulates the database

access, and adds domain logic on that data▪ Data Mapper– A layer of Mappers that moves data between objects and database

while keeping them independent

Pattern Overview

Data Source Layer▪ Domain layer has influence on the patterns▪ Transaction Script– Table Data Gateway for single access to a table– Row Data Gateway for single access to a row of a table▪ Domain Model– Active Record or Row Data Gateway– Data Mapper▪ Table Module– Table Data Gateway with Record Set

Data Source Patterns▪ Table Data Gateway– Acts as a Gateway to a database table▪ Row Data Gateway– Acts as a Gateway to a single record in a data source▪ Active Record– Wraps a row in a database table or view, encapsulates the database

access, and adds domain logic on that data▪ Data Mapper– A layer of Mappers that moves data between objects and database

while keeping them independent

Table Data GatewayAn object that acts as a Gateway to a database table. One

instance handles all the rows in the table.

▪ Also called Data Access Objects – DAO ▪ How It Works– Simple interface to a table with several find methods and methods

for maintaining data– CRUD methods (Create, Read, Update, Delete)– Acts as a gateway to a table– One gateway for each table– Finders return Collection of DTOs or Record Set

Table Data Gateway

▪ When to Use It– Works for Table Module since it is based on Record Set – Useful for web application where Domain Model is used

Row Data GatewayAn object that acts as a Gateway to a single record in a data

source. There is only one instance per row.

▪ How It Works– Object that is exactly one

single record– Each table column is a

field in the object– Do not have logic– Finder object– Can be generated

Row Data Gateway▪ When to Use It– Works well for simple domain layer for example Transaction Script

Active RecordAn object that wraps a row in a database table or view,

encapsulates the database access, and adds domain logic on that data

▪ How It Works– Each object can read and

store itself– Contain domain logic▪ When to Use It– When Domain Logic is not

too complex– When using Transaction Script

+insert()+update()+delete()+getExemption()+isFlaggedForAudit(in CompanyID)+getTaxableEarnings()

-lastname-firstname-NumerOfDependents

Person

Data MapperA layer of Mappers that moves data between objects and a

database while keeping them independent of each other and the mapper itself

▪ Separates the in-memory objects from the database

Data Mapper▪ How It works– Simple Data Mappers map in-memory object to table on a field-to-

field basis– Others need to map more complicated object hierarchies to multiple

tables– Mapper uses Identity Map to see if object is already loaded▪ For insert and updates– The mapper must know what objects have changed, which are new,

and which must be destroyed– Unit of Work pattern

Data Mapper▪ When to Use It– Database and object model must be independent– Data Mappers are useful with Domain Model – For simple Domain Model an Active Record could be used, but as

it becomes more complicated some mapping is needed▪ O/R mapping solutions can provide the mappers– For example Hibernate

Data Mapper▪ Simple example– Loading from the database

Data Mapper▪ Simple example– Updating data– Client asks the mapper to save a domain object– The mapper pulls the data out of the domain object and saves to the

database

DataSourceclassmapsnicelytotherowsinatableandcontainssomeusefulmethods

A) RowDataGateway B) TableDataGateway C) ActiveRecord D) DataMapper

QUIZ

Spring JDBC

Spring JDBC▪ Spring JDBC packages– org.springframework.jdbc ▪ datasource– Classes for connecting to the database▪ core– Base classes for accessing the database – JdbcTemplate ▪ object– Classes that support updating, inserting and deleting data from the

database▪ support– Utility classes

Loading the DataSource▪ Code

▪ Configuration – data.xml

Resource res = new FileSystemResource("data.xml"); XmlBeanFactory factory = new XmlBeanFactory(res); DataSource ds = (DataSource)factory.getBean("dataSource");

<beans> <bean id="dataSource“ class= "org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>net.sourceforge.jtds.jdbc.Driver</value> </property> <property name="url”> <value>jdbc:jtds:sqlserver://honn.ru.is:1433</value> </property> <property name="username"><value>andri</value></property> <property name="password"><value>abc123</value></property> </bean> </beans>

JdbcTemplate▪ Main class of core package– Simplifies queries▪ Template Method pattern– JdbcTemplate handles the

processing and calls our code– Dependency Injection

JdbcTemplate Example ParameterizedRowMapper<String> rm = new ParameterizedRowMapper<String>() { public String mapRow(ResultSet rs, int rowNum) throws SQLException { return rs.getString("title"); } };

JdbcTemplate tpl = new JdbcTemplate(getDataSource()); Collection<String> col = tpl.query("select * from contents", rm); for(String s : col) { System.out.println(s); }

Kenya's elephants send text messages to rangers (AP)

Flexible OLEDs could be part of lighting's future (AP)

Collecting Data▪ Spring Interface RowMapper– An interface used by JdbcTemplate for mapping returned result

sets

– Class that implements this interface can be used to collect data

public interface ParameterizedRowMapper<T> extends RowMapper<T> { Object mapRow(ResultSet rs, int rowNum) throws SQLException; }

ContentRowMapper

public class ContentRowMapper implements ParameterizedRowMapper<Content> { public Content mapRow(ResultSet rs, int rowNum) throws SQLException { Content content = new Content (rs.getInt (1), // id rs.getString (2), // title rs.getString (3), // link rs.getString (4), // description rs.getDate (5), // pubdate rs.getString(6)); // author return content; } }

Using ContentRowMapper▪ JdbcTemplate method query takes RowMapper interface as

parameter

ContentRowMapper crm = new ContentRowMapper();

JdbcTemplate tpl = new JdbcTemplate(ds); List l = tpl.query("select * from contents", crm);

Iterator i = l.iterator(); Content cont; while (i.hasNext()) { cont = (Content) i.next(); System.out.println(cont); }

Insert▪ SimpleJdbcInsert– Class for inserts

public int add(Content content) { SimpleJdbcInsert insertContent = new SimpleJdbcInsert(getDataSource()) .withTableName("contents") .usingGeneratedKeyColumns("id");

Map<String, Object> parameters = new HashMap<String, Object>(5); parameters.put("title", content.getTitle()); parameters.put("link", content.getLink()); parameters.put("description", content.getDescription()); parameters.put("pubdate", content.getPubDate()); parameters.put("author", content.getAuthor()); return insertContent.executeAndReturnKey(parameters).intValue(); }

RU Data Framework Content Example

Content Example▪ Table contents– Contains content information

CREATE TABLE contents ( id int Identity (1, 1) primary key NOT NULL, title varchar(128), link varchar(512) unique, description text, pubDate datetime, author varchar(128), )

Content Example▪ Gateway class for the contents table– ContentDataGateway interface contains the CRUD operations– Class ContentData implements the gateway and provides the

JDBC code– Content is simple

JavaBean – acts as Data Transfer Object

RU Data Framework▪ Classes and interfaces for accessing the database– Implementation of the Data Gateway ▪ For Table Data Gateway– Each table has an Gateway interface– Implementation in Data classes– Factory pattern returns the implementation for each Date Gateway

RuDataAccessFactory▪ Factory for creating Gateway interfaces– Reads information about the DataSource– Spring Bean Definition file: data.xml– Uses Spring Bean Factory – RuDataAccessFactory reads information on each gateway

interface and which classes to use as implementation– Code using the gateway interface calls getDataAccess in the

factory class

factory = RuDataAccessFactory.getInstance("data.xml"); contentDataGateway = (ContentDataGateway) factory.getDataAccess("contentDataAccess");

Data Definition▪ File data.xml

<beans> <!-- Data Source --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" > <property name="driv erClassName"> <value>net.sourceforge.jtds.jdbc.Driver</value></property> <property name="url"> <value>jdbc:jtds:sqlserver://honn.ru.is:1433</value></property> <property name="username"><value>andri</value></property> <property name="password"><value>abc123</value></property> </bean> <!– Content Gateway Interface --> <bean id="contentGateway" class="is.ru.honn.tube.data.content.ContentData"/> </bean> </beans>

DataSource▪ DataSource is a connection to a database– Driver Class Name (net.sourceforge.jtds.jdbc.Driver)– URL (jdbc:jtds:sqlserver://honn.ru.is:1433)– username (andri)– password (abc123)▪ RU framework uses Spring – Load the DataSource information– DriverManagerDataSource

extends AbstractDataSource which implements DataSource

DataSource in Ru Framework▪ RU Framework uses Spring to get DataSource

Using RU Framework

RuDataAccess▪ RuDataAccess is base interface for Data gateway interfaces– All gateway interfaces extend RuDataAccess– Has methods to set and get DataSource

RuData▪ RuData is a class implementing RuDataAccess– Handles DataSource– Data classes extend this class

ContentDataGateway▪ Contains all the method that are needed to manage contents– Gateway to the contents table– Pattern Table Data Gateway

public interface ContentDataGateway extends RuDataAccess { public int add(Content content); public List<Content> getContents(); }

ContentDatapublic class ContentData extends RuData implements ContentDataGateway { public int add(Content content) { SimpleJdbcInsert insertContent = new SimpleJdbcInsert(getDataSource()) .withTableName("contents") .usingGeneratedKeyColumns("id");

Map<String, Object> parameters = new HashMap<String, Object>(5); parameters.put("title", content.getTitle()); parameters.put("link", content.getLink()); parameters.put("description", content.getDescription()); parameters.put("pubdate", content.getPubDate()); parameters.put("author", content.getAuthor()); return insertContent.executeAndReturnKey(parameters).intValue(); }

ContentData public List getContents() { JdbcTemplate queryContent = new JdbcTemplate(getDataSource()); List<Content> contents = queryContent.query ("select * from contents", new ContentRowMapper()); return contents; }

Usagepublic class ContentServiceData implements ContentService { private ContentDataGateway contentDataGateway = null; public ContentServiceData() { RuDataAccessFactory factory = null; try { factory = RuDataAccessFactory.getInstance("data.xml"); } catch (RuException e) { ... } contentDataGateway = (ContentDataGateway) factory.getDataAccess("contentDataGateway"); } public void addContent(Content content) { contentDataGateway.add(content); } public List<Content> getContents() { return contentDataGateway.getContents(); } }

Contents▪ Use ContentServiceData instead of a Service Stub– Change one line in the app.xml file

<bean id="contentService" class="is.ru.honn.tube.service.ContentServiceData"> </bean>

Contents▪ Use ContentServiceData instead of a Service Stub– Change one line in the app.xml file

RU Database▪ hrnem.ru.is

▪ Each student has their own database▪ Username and passwords sent out▪ Check the access

Summary▪ Design Objectives– Object-relational impedance mismatch– The Usability Problem– The Legacy Problem▪ Patterns– Table Data Gateway– Row Data Gateway– Active Record– Data Mapper– Data Transfer Object and Record set