• No results found

Ruby on Rails. für Java Entwickler - Ende der Schmerzen - first, last = :mariano, :kamp =

N/A
N/A
Protected

Academic year: 2021

Share "Ruby on Rails. für Java Entwickler - Ende der Schmerzen - first, last = :mariano, :kamp ="

Copied!
242
0
0

Loading.... (view fulltext now)

Full text

(1)

Ruby on Rails

für Java Entwickler

Ende der Schmerzen

-first, last = :mariano, :kamp

(2)

Ruby on Rails

für Java Entwickler

Ende der Schmerzen

-first, last = :mariano, :kamp

(3)
(4)
(5)
(6)
(7)
(8)

Ein Ritter in

(9)
(10)
(11)

Yukihiro

(12)

Yukihiro

Matsumoto

“Matz”

(13)

Suche nach dem

Edelstein

(14)
(15)

Smalltalk

Perl

+

~=

Ruby

(16)

Smalltalk

Perl

+

~=

Ruby

objektorientierung

dynamik

http://flickr.com/photos/letioux/110269051/

(17)

Smalltalk

Perl

+

~=

Ruby

objektorientierung

reguläre ausdrücke

string

manipulationen

dynamik

(18)
(19)
(20)
(21)
(22)

“then computers”

(23)
(24)

objektorientierung

kapselung

vererbung

(25)
(26)

“everything is an object”

(27)

ja, ja ...

(28)

nein, diesmal wirklich!

(29)

>> "ruby".class

=> String

(30)

IRB-In

>> "ruby".class

=> String

(31)

IRB-Out

>> "ruby".class

=> String

(32)

>> 10.class

=> Fixnum

(33)

>> 10.class

=> Fixnum

objektorientierung

Primitives sind keine

Objekte!

(34)

>> nil.class

=> NilClass

(35)

>> nil.class

=> NilClass

objektorientierung

Schlüsselwort “null”

(36)

>> true.class

=> TrueClass

(37)

>> true.class

=> TrueClass

objektorientierung

Schlüsselwort “true”

(38)

objekte senden und

empfangen nachrichten

(39)

>> 10.div(2)

=> 5

(40)

>> 10.div(2)

=> 5

objektorientierung

Nicht für Primitives

(41)

>> 10.send(:div, 2)

=> 5

(42)

>> 10./2

=> 5

(43)

>> 10/2

=> 5

(44)

>> 10/2

=> 5

objektorientierung

Nur für Primitives

(45)

>> 10.send(:/, 2)

=> 5

(46)

>> String.new "ruby"

=> "ruby"

(47)

>> String.new "ruby"

=> "ruby"

objektorientierung

Schlüsselwort “new”

(48)

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

(49)

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

(50)

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

(51)

Define a “setter”

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

(52)

Define a “getter”

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

(53)

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

>> d = Dog.new

=> #<Dog:0x1d4bac>

>> d.name="Fluffy"

=> "Fluffy"

>> d.name

=> "Fluffy"

(54)

“Dog d = new Dog()”

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

>> d = Dog.new

=> #<Dog:0x1d4bac>

>> d.name="Fluffy"

=> "Fluffy"

>> d.name

=> "Fluffy"

(55)

“d.setName(“Fluffy”)”

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

>> d = Dog.new

=> #<Dog:0x1d4bac>

>> d.name="Fluffy"

=> "Fluffy"

>> d.name

=> "Fluffy"

(56)

“d.getName()”

>> class Dog

>> def name=(new_name)

>> @name=new_name

>> end

>> def name

>> @name

>> end

>> end

=> nil

objektorientierung

>> d = Dog.new

=> #<Dog:0x1d4bac>

>> d.name="Fluffy"

=> "Fluffy"

>> d.name

=> "Fluffy"

(57)
(58)
(59)

“everything is open”

(60)

sogar die ruby libraries

(61)

>> class Fixnum

>> def even?

>> self % 2 == 0

>> end

>> end

=> nil

>> 10.even?

=> true

>> 9.even?

=> false

dynamik

(62)

>> class Fixnum

>> def even?

>> self % 2 == 0

>> end

>> end

=> nil

>> 10.even?

=> true

>> 9.even?

=> false

dynamik

Subclassing, wenn erlaubt

Helper Klassen -> StringUtil

(63)

und bereits lebende

objekte

(64)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

(65)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

(66)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

(67)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

(68)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

(69)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

(70)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

(71)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

dynamik

>> Player.find(:all).size

=> 4

(72)

class << ActiveRecord::Base.connection

alias :__old_execute__ :execute

def execute(statement, name)

puts "Executing: #{statement}"

__old_execute__(statement, name)

end

end

dynamik

>> Player.find(:all).size

Executing: SELECT * FROM players

=> 4

(73)
(74)

dynamik

(75)

strong/static typing

dynamik

(76)

strong/static typing

dynamik

weak typing

(77)

dynamik

>> def sum(a, b)

>> a+b

>> end

=> nil

dynamic typing

(78)

dynamik

>> def sum(a, b)

>> a+b

>> end

=> nil

>> sum(1,2)

=> 3

dynamic typing

(79)

dynamik

>> def sum(a, b)

>> a+b

>> end

=> nil

>> sum("A","Z")

=> "AZ"

dynamic typing

(80)

dynamik

>> def sum(a, b)

>> a+b

>> end

=> nil

>> sum("A",2)

dynamic typing

(81)

dynamik

>> def sum(a, b)

>> a+b

>> end

=> nil

>> sum("A",2)

dynamic typing

TypeError: can't convert Fixnum into

String

(82)

:method_missing

(83)

dynamik

>> class Receiver

>> def method_missing(action, *args)

>> puts "My method #{action} was called,"

>> puts "with parameters: #{args.inspect}"

>> end

(84)

dynamik

>> class Receiver

>> def method_missing(action, *args)

>> puts "My method #{action} was called,"

>> puts "with parameters: #{args.inspect}"

>> end

>> end

>> r = Receiver.new

(85)

dynamik

>> class Receiver

>> def method_missing(action, *args)

>> puts "My method #{action} was called,"

>> puts "with parameters: #{args.inspect}"

>> end

>> end

>> r = Receiver.new

=> #<Receiver:0x33d43c>

>> r.test

My method test was called,

with parameters: []

(86)

dynamik

>> class Receiver

>> def method_missing(action, *args)

>> puts "My method #{action} was called,"

>> puts "with parameters: #{args.inspect}"

>> end

>> end

>> r.add 1,"b", 2

My method add was called,

with parameters: [1, "b", 2]

=> nil

>> r = Receiver.new

=> #<Receiver:0x33d43c>

>> r.test

My method test was called,

with parameters: []

(87)

dynamik

>> class Receiver

>> def method_missing(action, *args)

>> puts "My method #{action} was called,"

>> puts "with parameters: #{args.inspect}"

>> end

>> end

Proxy?

Mock?

State Machine?

CSV Reader?

AOP?

>> r.add 1,"b", 2

My method add was called,

with parameters: [1, "b", 2]

=> nil

>> r = Receiver.new

=> #<Receiver:0x33d43c>

>> r.test

My method test was called,

with parameters: []

(88)

meta programmierung

(89)

dynamik

>> class Dog

>> attr_accessor :name, :age

>> def age=(new_age)

>> @age=new_age*7

>> end

>> end

=> nil

(90)

dynamik

>> class Dog

>> attr_accessor :name, :age

>> def age=(new_age)

>> @age=new_age*7

>> end

>> end

=> nil

Definiert “on the fly”:

(91)

dynamik

>> class Dog

>> attr_accessor :name, :age

>> def age=(new_age)

>> @age=new_age*7

>> end

>> end

=> nil

(92)

dynamik

>> class Dog

>> attr_accessor :name, :age

>> def age=(new_age)

>> @age=new_age*7

>> end

>> end

=> nil

>> d = Dog.new

=> #<Dog:0x318498>

(93)

dynamik

>> class Dog

>> attr_accessor :name, :age

>> def age=(new_age)

>> @age=new_age*7

>> end

>> end

=> nil

>> d.name = "Fluffy"

=> "Fluffy"

>> d.age = 2

=> 2

(94)

dynamik

>> class Dog

>> attr_accessor :name, :age

>> def age=(new_age)

>> @age=new_age*7

>> end

>> end

=> nil

>> d.age

=> 14

(95)

und vieles mehr ...

(96)

blocks/closures

(97)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

(98)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

(99)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

>> end

>> log("Addition"){1+1}

Now executing Addition.

Done with Addition.

(100)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

>> end

>> log("Addition"){1+1}

Now executing Addition.

Done with Addition.

(101)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

>> end

>> log("Addition"){1+1}

Now executing Addition.

Done with Addition.

(102)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

>> end

>> log("Addition"){1+1}

Now executing Addition.

Done with Addition.

(103)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

>> end

>> log("Addition"){1+1}

Now executing Addition.

Done with Addition.

(104)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

>> end

>> log("Addition"){1+1}

Now executing Addition.

Done with Addition.

=> 2

>> log("Output"){puts "Chunky Bacon"}

Now executing Output.

Chunky Bacon

Done with Output.

=> nil

(105)

closures

>> def log(name)

>> puts "Now executing #{name}."

>> result = yield

>> puts "Done with #{name}."

>> result

>> end

>> ["chunky","bacon"].each {|element| puts element}

chunky

bacon

>> log("Addition"){1+1}

Now executing Addition.

Done with Addition.

=> 2

>> log("Output"){puts "Chunky Bacon"}

Now executing Output.

Chunky Bacon

Done with Output.

=> nil

(106)
(107)
(108)
(109)
(110)
(111)
(112)

Pragmatic Programmers

"Learn at least one new

[programming] language every year.”

“Different languages solve the same problems

in different ways. By learning several different

approaches, you can help broaden your

(113)
(114)

Google Trends

(115)

Programming Language Trends

(116)
(117)
(118)
(119)
(120)
(121)
(122)

I always knew one day Smalltalk would replace Java.

I just didn't know it would be called Ruby.

(123)
(124)
(125)
(126)
(127)

I like the ruby language for its rich yet uncluttered syntax

and the well designed frameworks that come with it.

(128)
(129)
(130)
(131)
(132)
(133)
(134)

David Heinemeier Hanson

(135)
(136)
(137)
(138)

extrahiert aus

(139)

conventions

configuration

(140)

over

conventions

configuration

(141)
(142)

zuckerbrot

&

(143)

DRY

(don’t repeat yourself)

(144)
(145)
(146)

conventions

(147)

conventions

Klassen- und Tabellen

Klassennamen sind Singular.

Tabellennamen sind Plural.

(148)

conventions

Klassen- und Tabellen

Klassennamen sind Singular.

Tabellennamen sind Plural.

Klassennamen sind CamelCase.

Tabellennamen sind Kleinbuchstaben, verbunden

durch “_”.

(149)

conventions

Klassen- und Tabellen

Klassennamen sind Singular.

Tabellennamen sind Plural.

Klassennamen sind CamelCase.

Tabellennamen sind Kleinbuchstaben, verbunden

durch “_”.

Bsp.:

TurnState => turn_states

OrderReceipt => order_receipts

Person => people

(150)

conventions

Spalten- und Attribute

Spaltenname == Attributname

Jede Tabelle hat eine “id”-Spalte

(151)

conventions

Relationen

Spaltennamen des foreign keys entspricht

dem Namen der Klasse plus “_id”.

(152)

conventions

Relationen

Spaltennamen des foreign keys entspricht

dem Namen der Klasse plus “_id”.

*

id

name

author

Book

id

name

Customer

(153)

conventions

Relationen

Spaltennamen des foreign keys entspricht

dem Namen der Klasse plus “_id”.

*

id

name

author

Book

id

name

Customer

Der Tabelle books wird die Spalte

customer_id angefügt.

(154)

conventions

(155)

und?

(156)

JEE vs Rails

(157)

JEE vs Rails

*

id

name

author

Book

id

name

Customer

http://www.laliluna.de/ejb-3-struts-tutorial-jboss.html

Java Beispielcode von

Sebastian Hennebrueder

(158)

JEE vs Rails

/**

*

* @author Sebastian Hennebrueder

* created Mar 15, 2006

* copyright 2006 by http://www.laliluna.de

*/

package de.laliluna.library;

import java.util.ArrayList;

import java.util.List;

import java.util.Set;

import javax.persistence.CascadeType;

import javax.persistence.Entity;

import javax.persistence.FetchType;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.OneToMany;

import javax.persistence.SequenceGenerator;

import javax.persistence.Table;

/**

* @author hennebrueder

*

*/

@Entity

@Table(name="customer")

@SequenceGenerator(name="customer_sequence", sequenceName="customer_id_seq")

public class Customer {

private Integer id;

private String name;

private List books =new ArrayList();

public Customer(){

super();

}

public Customer(Integer id, String name){

super();

this.id=id;

this.name=name;

}

@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="customer",

targetEntity=Book.class)

public List getBooks() {

return books;

}

public void setBooks(List books) {

this.books = books;

}

@Id

@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="customer_sequence")

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "Customer: " + getId() + " Name " + getName();

}

}

id

name

(159)

Model -> Table

@Entity

@Table(name="customer")

[..]

public class Customer {

[..]

id

name

Customer

Rails:

class Customer < ActiveRecord::Base

end

Convention:

Class Name = “Customer” => Table Name = “Customers”

sonst: set_table_name(“customer”)

(160)

[..]

@SequenceGenerator(name="customer_sequence",

sequenceName="customer_id_seq")

public class Customer {

[..]

@Id

@GeneratedValue(strategy=GenerationType.SEQUENCE,

generator="customer_sequence")

public Integer getId() {

id

name

Customer

Rails: Entfällt.

Convention:

Primary Key => “id”, sequence

(161)

@OneToMany(cascade=CascadeType.ALL,

fetch = FetchType.EAGER,

mappedBy="customer",

targetEntity=Book.class)

public List getBooks() {

return books;

}

public void setBooks(List books) {

this.books = books;

}

id

name

Customer

Rails:

has_many :books

Convention:

targetEntity = Singular des Entitätennames, sonst “, :class_name = “Book”

Getter/Setter dynamisch

(162)

private Integer id;

private String name;

private List books =new ArrayList();

public Customer(){ super(); }

public Customer(Integer id, String name){

super(); this.id=id; this.name=name;

}

public Integer getId() { return id; }

public void setId(Integer id) { this.id = id;}

public String getName() { return name;}

public void setName(String name) { this.name = name;}

id

name

Customer

Rails:

create_table :customers do |t|

# keine “id” spalte

t.column :name, :string

end

Attributes

Convention:

Name der Spalte =

Name des Attributs

(163)

@Override

public String toString() {

return "Customer: "+getId()+" Name "+getName();

}

id

name

Customer

Rails:

Entfällt, Default:

#<Customer:0x2417c14 @attributes={"name"=>"Donald Duck", "id"=>"1"}>

Alternativ:

def to_s

“Customer: #{id} Name #{name}”

end

=> "Customer: 1 Name Donald Duck"

(164)

save/persist

merge

findAll

findById

findByCustomer (BookDAO...)

id

name

Customer

Rails:

Alle Methoden bereits im Framework generisch enthalten

“findByX” dynamisch -> findByName, findByAuthor, findByCustomer,

findByTitleAndAuthor ...

CustomerDAO,

CustomerDAOImpl

id

name

author

Book

(165)

class Initial < ActiveRecord::Migration

def self.up

create_table :books do |t|

t.column :name, :string

t.column :author, :string

t.column :customer_id, :integer

end

create_table :customers do |t|

t.column :name, :string

end

end

def self.down

drop_table :books

drop_table :customers

end

end

Migration

*

id

name

author

Book

id

name

Customer

(166)

class Initial < ActiveRecord::Migration

def self.up

create_table :books do |t|

t.column :name, :string

t.column :author, :string

t.column :customer_id, :integer

end

create_table :customers do |t|

t.column :name, :string

end

end

def self.down

drop_table :books

drop_table :customers

end

end

Migration

*

id

name

author

Book

id

name

Customer

(167)

class Initial < ActiveRecord::Migration

def self.up

create_table :books do |t|

t.column :name, :string

t.column :author, :string

t.column :customer_id, :integer

end

create_table :customers do |t|

t.column :name, :string

end

end

def self.down

drop_table :books

drop_table :customers

end

end

Migration

*

id

name

author

Book

id

name

Customer

(168)

class Initial < ActiveRecord::Migration

def self.up

create_table :books do |t|

t.column :name, :string

t.column :author, :string

t.column :customer_id, :integer

end

create_table :customers do |t|

t.column :name, :string

end

end

def self.down

drop_table :books

drop_table :customers

end

end

Migration

*

id

name

author

Book

id

name

Customer

(169)

class Initial < ActiveRecord::Migration

def self.up

create_table :books do |t|

t.column :name, :string

t.column :author, :string

t.column :customer_id, :integer

end

create_table :customers do |t|

t.column :name, :string

end

end

def self.down

drop_table :books

drop_table :customers

end

end

Migration

*

id

name

author

Book

id

name

Customer

(170)

class Initial < ActiveRecord::Migration

def self.up

create_table :books do |t|

t.column :name, :string

t.column :author, :string

t.column :customer_id, :integer

end

create_table :customers do |t|

t.column :name, :string

end

end

def self.down

drop_table :books

drop_table :customers

end

end

Migration

*

id

name

author

Book

id

name

Customer

(171)

class Initial < ActiveRecord::Migration

def self.up

create_table :books do |t|

t.column :name, :string

t.column :author, :string

t.column :customer_id, :integer

end

create_table :customers do |t|

t.column :name, :string

end

end

def self.down

drop_table :books

drop_table :customers

end

end

Migration

*

id

name

author

Book

id

name

Customer

(172)

class Customer < ActiveRecord::Base

has_many :books

end

class Book < ActiveRecord::Base

belongs_to :customer

end

Der Code

*

id

name

author

Book

id

name

Customer

(173)

Perfection in Design

This Wikipedia and Wikimedia Commons image is from the user Chris 73 and is freely available at http://commons.wikimedia.org/

wiki/Image:Antoine_de_Saint-Exup%C3%A9ry_Lyon.JPG under the creative commons cc-by-sa 2.5 license.

(174)

Perfection in Design

Antoine de Saint-Exupéry

This Wikipedia and Wikimedia Commons image is from the user Chris 73 and is freely available at http://commons.wikimedia.org/

wiki/Image:Antoine_de_Saint-Exup%C3%A9ry_Lyon.JPG under the creative commons cc-by-sa 2.5 license.

(175)

Perfection in Design

Antoine de Saint-Exupéry

This Wikipedia and Wikimedia Commons image is from the user Chris 73 and is freely available at http://commons.wikimedia.org/

wiki/Image:Antoine_de_Saint-Exup%C3%A9ry_Lyon.JPG under the creative commons cc-by-sa 2.5 license.

“You know you’ve achieved perfection

in design, not when you have nothing

more to add, but when you have

(176)

JEE vs Rails

Migration

Customer

Book

(177)

JEE vs Rails

/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.SequenceGenerator;import javax.persistence.Table; /** * @author hennebrueder * */ @Entity @Table(name="customer") @SequenceGenerator(name="customer_sequence", sequenceName="customer_id_seq")

public class Customer { private Integer id; private String name; private List books =new ArrayList();

public Customer(){ super(); } public Customer(Integer id, String name){ super();

this.id=id; this.name=name;

}

@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="customer", targetEntity=Book.class) public List getBooks() { return books; } public void setBooks(List books) {

this.books = books; } @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="customer_sequence") public Integer getId() {

return id; } public void setId(Integer id) {

this.id = id; } public String getName() {

return name; } public void setName(String name) {

this.name = name; } @Override public String toString() { return "Customer: " + getId() + " Name " + getName();

} }/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.List; import javax.ejb.Stateless; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; /** * @author hennebrueder * */ @Stateless public class CustomerDaoImp implements CustomerDao {

@PersistenceContext private EntityManager em; public static final String RemoteJNDIName = CustomerDaoImp.class.getSimpleName() + "/remote"; public static final String LocalJNDIName = CustomerDaoImp.class.getSimpleName() + "/local";

/* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#save(de.laliluna.example.ejb.Book) */

public void save(Customer customer) { em.persist(customer); } /* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#reattach(de.laliluna.example.ejb.Book) */

public void merge(Customer customer) { em.merge(customer); } /* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#findAll() */

public List findAll() { return em.createQuery("from Customer").getResultList(); }

/* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#findById(java.lang.Integer) */

public Customer findById(Integer id) { Customer customer = em.find(Customer.class, id);

return customer; }

}

/** * * @author Sebastian Hennebrueder * created Feb 27, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.ArrayList;import java.util.List; import javax.ejb.Stateful; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.apache.log4j.Logger; import sun.security.krb5.internal.crypto.bo; /** * @author hennebrueder * */ @Stateless public class BookDaoImp implements BookDao {

@PersistenceContext private EntityManager em; private Logger log = Logger.getLogger(this.getClass());

/* * (non-Javadoc)

* * @see de.laliluna.example.ejb.BookDao#save(de.laliluna.example.ejb.Book)

*/ public void save(Book book) { log.debug("Persist book: " + book); em.persist(book); } public void merge(Book book) {

em.merge(book); } public List findAll() { log.debug("find All books"); return em.createQuery("from Book").getResultList(); } public static final String RemoteJNDIName = BookDaoImp.class

.getSimpleName() + "/remote"; public static final String LocalJNDIName = BookDaoImp.class.getSimpleName()

+ "/local"; public Book findById(Integer id) { return em.find(Book.class, id);

} public List findByCustomer(Customer customer) { log.debug("find by customer"); return em.createQuery("from Book b where b.customer = :customer") .setParameter("customer", customer).getResultList();

}} package de.laliluna.library; import java.util.List; import javax.ejb.Local; import org.jboss.annotation.ejb.LocalBinding; @Local public interface BookDao { public void save(Book book); public void merge(Book book); public List findAll(); public List findByCustomer(Customer customer);

public Book findById(Integer id); }/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.List; import javax.ejb.Local; /** * @author hennebrueder * */ @Local public interface CustomerDao { public void save(Customer customer); public void merge(Customer customer); public List findAll(); public Customer findById(Integer id);} /** * * @author Sebastian Hennebrueder * created Feb 27, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType;import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.SequenceGenerator;import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; /** * @author hennebrueder * */ @Entity @Table(name = "book") @SequenceGenerator(name = "book_sequence", sequenceName = "book_id_seq")

public class Book implements Serializable { private Integer id; private String title; private String author; private Customer customer; public Book() {

super(); } public Book(Integer id, String title, String author) {

super(); this.id = id; this.title = title; this.author = author; } @ManyToOne @JoinColumn(name = "customer_id")

public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer;

} public String getAuthor() { return author;

} public void setAuthor(String author) { this.author = author;

} @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_sequence")

public Integer getId() { return id; } public void setId(Integer id) { this.id = id;

} public String getTitle() { return title;

} public void setTitle(String title) { this.title = title;

} @Override public String toString() { return "Book: " + getId() + " Title " + getTitle() + " Author "

+ getAuthor(); }

}

Migration

Customer

Book

(178)

JEE vs Rails

/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.SequenceGenerator;import javax.persistence.Table; /** * @author hennebrueder * */ @Entity @Table(name="customer") @SequenceGenerator(name="customer_sequence", sequenceName="customer_id_seq")

public class Customer { private Integer id; private String name; private List books =new ArrayList();

public Customer(){ super(); } public Customer(Integer id, String name){ super();

this.id=id; this.name=name;

}

@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="customer", targetEntity=Book.class) public List getBooks() { return books; } public void setBooks(List books) {

this.books = books; } @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="customer_sequence") public Integer getId() {

return id; } public void setId(Integer id) {

this.id = id; } public String getName() {

return name; } public void setName(String name) {

this.name = name; } @Override public String toString() { return "Customer: " + getId() + " Name " + getName();

} }/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.List; import javax.ejb.Stateless; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; /** * @author hennebrueder * */ @Stateless public class CustomerDaoImp implements CustomerDao {

@PersistenceContext private EntityManager em; public static final String RemoteJNDIName = CustomerDaoImp.class.getSimpleName() + "/remote"; public static final String LocalJNDIName = CustomerDaoImp.class.getSimpleName() + "/local";

/* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#save(de.laliluna.example.ejb.Book) */

public void save(Customer customer) { em.persist(customer); } /* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#reattach(de.laliluna.example.ejb.Book) */

public void merge(Customer customer) { em.merge(customer); } /* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#findAll() */

public List findAll() { return em.createQuery("from Customer").getResultList(); }

/* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#findById(java.lang.Integer) */

public Customer findById(Integer id) { Customer customer = em.find(Customer.class, id);

return customer; }

}

/** * * @author Sebastian Hennebrueder * created Feb 27, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.ArrayList;import java.util.List; import javax.ejb.Stateful; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.apache.log4j.Logger; import sun.security.krb5.internal.crypto.bo; /** * @author hennebrueder * */ @Stateless public class BookDaoImp implements BookDao {

@PersistenceContext private EntityManager em; private Logger log = Logger.getLogger(this.getClass());

/* * (non-Javadoc)

* * @see de.laliluna.example.ejb.BookDao#save(de.laliluna.example.ejb.Book)

*/ public void save(Book book) { log.debug("Persist book: " + book); em.persist(book); } public void merge(Book book) {

em.merge(book); } public List findAll() { log.debug("find All books"); return em.createQuery("from Book").getResultList(); } public static final String RemoteJNDIName = BookDaoImp.class

.getSimpleName() + "/remote"; public static final String LocalJNDIName = BookDaoImp.class.getSimpleName()

+ "/local"; public Book findById(Integer id) { return em.find(Book.class, id);

} public List findByCustomer(Customer customer) { log.debug("find by customer"); return em.createQuery("from Book b where b.customer = :customer") .setParameter("customer", customer).getResultList();

}} package de.laliluna.library; import java.util.List; import javax.ejb.Local; import org.jboss.annotation.ejb.LocalBinding; @Local public interface BookDao { public void save(Book book); public void merge(Book book); public List findAll(); public List findByCustomer(Customer customer);

public Book findById(Integer id); }/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.List; import javax.ejb.Local; /** * @author hennebrueder * */ @Local public interface CustomerDao { public void save(Customer customer); public void merge(Customer customer); public List findAll(); public Customer findById(Integer id);} /** * * @author Sebastian Hennebrueder * created Feb 27, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType;import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.SequenceGenerator;import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; /** * @author hennebrueder * */ @Entity @Table(name = "book") @SequenceGenerator(name = "book_sequence", sequenceName = "book_id_seq")

public class Book implements Serializable { private Integer id; private String title; private String author; private Customer customer; public Book() {

super(); } public Book(Integer id, String title, String author) {

super(); this.id = id; this.title = title; this.author = author; } @ManyToOne @JoinColumn(name = "customer_id")

public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer;

} public String getAuthor() { return author;

} public void setAuthor(String author) { this.author = author;

} @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_sequence")

public Integer getId() { return id; } public void setId(Integer id) { this.id = id;

} public String getTitle() { return title;

} public void setTitle(String title) { this.title = title;

} @Override public String toString() { return "Book: " + getId() + " Title " + getTitle() + " Author "

+ getAuthor(); }

}

class Customer < ActiveRecord::Base has_many :books end class Book < ActiveRecord::Base

belongs_to :customerend class Initial < ActiveRecord::Migration def self.up

create_table :books do |t| t.column :name, :string t.column :author, :string t.column :customer_id, :integer end create_table :customers do |t|

t.column :name, :string end end def self.down drop_table :books drop_table :customers end end

Migration

Customer

Book

(179)

JEE vs Rails

/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.SequenceGenerator;import javax.persistence.Table; /** * @author hennebrueder * */ @Entity @Table(name="customer") @SequenceGenerator(name="customer_sequence", sequenceName="customer_id_seq")

public class Customer { private Integer id; private String name; private List books =new ArrayList();

public Customer(){ super(); } public Customer(Integer id, String name){ super();

this.id=id; this.name=name;

}

@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="customer", targetEntity=Book.class) public List getBooks() { return books; } public void setBooks(List books) {

this.books = books; } @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="customer_sequence") public Integer getId() {

return id; } public void setId(Integer id) {

this.id = id; } public String getName() {

return name; } public void setName(String name) {

this.name = name; } @Override public String toString() { return "Customer: " + getId() + " Name " + getName();

} }/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.List; import javax.ejb.Stateless; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; /** * @author hennebrueder * */ @Stateless public class CustomerDaoImp implements CustomerDao {

@PersistenceContext private EntityManager em; public static final String RemoteJNDIName = CustomerDaoImp.class.getSimpleName() + "/remote"; public static final String LocalJNDIName = CustomerDaoImp.class.getSimpleName() + "/local";

/* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#save(de.laliluna.example.ejb.Book) */

public void save(Customer customer) { em.persist(customer); } /* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#reattach(de.laliluna.example.ejb.Book) */

public void merge(Customer customer) { em.merge(customer); } /* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#findAll() */

public List findAll() { return em.createQuery("from Customer").getResultList(); }

/* (non-Javadoc) * @see de.laliluna.example.ejb.CustomerDao#findById(java.lang.Integer) */

public Customer findById(Integer id) { Customer customer = em.find(Customer.class, id);

return customer; }

}

/** * * @author Sebastian Hennebrueder * created Feb 27, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.ArrayList;import java.util.List; import javax.ejb.Stateful; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.apache.log4j.Logger; import sun.security.krb5.internal.crypto.bo; /** * @author hennebrueder * */ @Stateless public class BookDaoImp implements BookDao {

@PersistenceContext private EntityManager em; private Logger log = Logger.getLogger(this.getClass());

/* * (non-Javadoc)

* * @see de.laliluna.example.ejb.BookDao#save(de.laliluna.example.ejb.Book)

*/ public void save(Book book) { log.debug("Persist book: " + book); em.persist(book); } public void merge(Book book) {

em.merge(book); } public List findAll() { log.debug("find All books"); return em.createQuery("from Book").getResultList(); } public static final String RemoteJNDIName = BookDaoImp.class

.getSimpleName() + "/remote"; public static final String LocalJNDIName = BookDaoImp.class.getSimpleName()

+ "/local"; public Book findById(Integer id) { return em.find(Book.class, id);

} public List findByCustomer(Customer customer) { log.debug("find by customer"); return em.createQuery("from Book b where b.customer = :customer") .setParameter("customer", customer).getResultList();

}} package de.laliluna.library; import java.util.List; import javax.ejb.Local; import org.jboss.annotation.ejb.LocalBinding; @Local public interface BookDao { public void save(Book book); public void merge(Book book); public List findAll(); public List findByCustomer(Customer customer);

public Book findById(Integer id); }/** * * @author Sebastian Hennebrueder

* created Mar 15, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.util.List; import javax.ejb.Local; /** * @author hennebrueder * */ @Local public interface CustomerDao { public void save(Customer customer); public void merge(Customer customer); public List findAll(); public Customer findById(Integer id);} /** * * @author Sebastian Hennebrueder * created Feb 27, 2006 * copyright 2006 by http://www.laliluna.de */ package de.laliluna.library; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType;import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.SequenceGenerator;import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; /** * @author hennebrueder * */ @Entity @Table(name = "book") @SequenceGenerator(name = "book_sequence", sequenceName = "book_id_seq")

public class Book implements Serializable { private Integer id; private String title; private String author; private Customer customer; public Book() {

super(); } public Book(Integer id, String title, String author) {

super(); this.id = id; this.title = title; this.author = author; } @ManyToOne @JoinColumn(name = "customer_id")

public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer;

} public String getAuthor() { return author;

} public void setAuthor(String author) { this.author = author;

} @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_sequence")

public Integer getId() { return id; } public void setId(Integer id) { this.id = id;

} public String getTitle() { return title;

} public void setTitle(String title) { this.title = title;

} @Override public String toString() { return "Book: " + getId() + " Title " + getTitle() + " Author "

+ getAuthor(); }

}

class Customer < ActiveRecord::Base has_many :books end class Book < ActiveRecord::Base

belongs_to :customerend class Initial < ActiveRecord::Migration def self.up

create_table :books do |t| t.column :name, :string t.column :author, :string t.column :customer_id, :integer end create_table :customers do |t|

t.column :name, :string end end def self.down drop_table :books drop_table :customers end end

Migration

Customer

Book

(180)
(181)

/ Noise

Signal

(182)

public void testBook() {

Book book = new Book(null,"My first bean book", "Sebastian");

em.persist(book);

Book book2 = new Book(null,"another book", "Paul");

em.persist(book2);

Book book3 = new Book(null,"EJB 3 developer guide","Sebastian");

em.persist(book3);

[..]

/ Noise

def test_book

book = Book.create(:name => "My first bean book",

:author => "Sebastian")

book2 = Book.create(:name => "another book",

:author => "Paul")

book3 = Book.create(:name => "EJB 3 dev guide",

:author => "Sebastian")

[..]

(183)

public void testBook() {

Book book = new Book(null,"My first bean book", "Sebastian");

em.persist(book);

Book book2 = new Book(null,"another book", "Paul");

em.persist(book2);

Book book3 = new Book(null,"EJB 3 developer guide","Sebastian");

em.persist(book3);

[..]

/ Noise

def test_book

book = Book.create(:name => "My first bean book",

:author => "Sebastian")

book2 = Book.create(:name => "another book",

:author => "Paul")

book3 = Book.create(:name => "EJB 3 dev guide",

:author => "Sebastian")

[..]

(184)

[..]

System.out.println("list some books");

List someBooks =

em.createQuery("from Book b where b.author=:name")

.setParameter("name", "Sebastian").getResultList();

for (Iterator iter = someBooks.iterator(); iter.hasNext();){

Book element = (Book) iter.next();

System.out.println(element);

}

System.out.println("list all books");

List allBooks = em.createQuery("from Book").getResultList();

for (Iterator iter = allBooks.iterator(); iter.hasNext();){

Book element = (Book) iter.next();

System.out.println(element);

}

[..]

puts "list some books"

Book.find_all_by_author("Sebastian").each {|book| puts book.inspect}

puts "list all books"

Book.find(:all).each {|book| puts book.inspect}

/ Noise

Signal

(185)

[..]

System.out.println("list some books");

List someBooks =

em.createQuery("from Book b where b.author=:name")

.setParameter("name", "Sebastian").getResultList();

for (Iterator iter = someBooks.iterator(); iter.hasNext();){

Book element = (Book) iter.next();

System.out.println(element);

}

System.out.println("list all books");

List allBooks = em.createQuery("from Book").getResultList();

for (Iterator iter = allBooks.iterator(); iter.hasNext();){

Book element = (Book) iter.next();

System.out.println(element);

}

[..]

puts "list some books"

Book.find_all_by_author("Sebastian").each {|book| puts book.inspect}

puts "list all books"

Book.find(:all).each {|book| puts book.inspect}

/ Noise

Signal

(186)

[..]

System.out.println("list some books");

List someBooks =

em.createQuery("from Book b where b.author=:name")

.setParameter("name", "Sebastian").getResultList();

for (Iterator iter = someBooks.iterator(); iter.hasNext();){

Book element = (Book) iter.next();

System.out.println(element);

}

System.out.println("list all books");

List allBooks = em.createQuery("from Book").getResultList();

for (Iterator iter = allBooks.iterator(); iter.hasNext();){

Book element = (Book) iter.next();

System.out.println(element);

}

[..]

puts "list some books"

Book.find_all_by_author("Sebastian").each {|book| puts book.inspect}

puts "list all books"

Book.find(:all).each {|book| puts book.inspect}

/ Noise

Signal

JDK 1.5 to the rescue

(Generics, foreach)

(187)

public void testRelation() {

[..] Drei Books und zwei Customers angelegt

customer1.getBooks().add(book);

book.setCustomer(customer1);

customer2.getBooks().add(book2);

customer2.getBooks().add(book3);

[..] Drei Books und zwei Customers angelegt

customer1.books << book

customer2.books << [book2, book3]

/ Noise

Signal

(188)

public void testRelation() {

[..] Drei Books und zwei Customers angelegt

customer1.getBooks().add(book);

book.setCustomer(customer1);

customer2.getBooks().add(book2);

customer2.getBooks().add(book3);

[..] Drei Books und zwei Customers angelegt

customer1.books << book

customer2.books << [book2, book3]

/ Noise

Signal

(189)

class Book < ActiveRecord::Base

belongs_to :customer

has_many :chapters

has_many :sections, :through => :chapters

validates_presence_of :author

validates_uniqueness_of :name

validates_length_of :name, :within => 6..20,

:too_long => "pick shorter name",

:too_short => "pick longer name"

end

(190)

Batteries included

Rails bringt einiges mit:

Struktur

Build

Testunterstützung

Entwicklungs-, Test- und Produktionsumgebung

Kein eigenes Denken notwendig

Skripte und Automatismen verwenden gleiche

(191)
(192)
(193)
(194)
(195)
(196)
(197)
(198)
(199)
(200)<

References

Related documents

Still unsolved, methodologies that use a common description tool for all stakeholders implied, summarizing technological, functional and non-functional information

Chapter 7: How to Learn Languages Quickly If you’re going to spend any significant amount of time in a foreign country, then you’re going to want to be able to communicate at least

a Refit the automatic transmission bell housing upper bolts. a Torque tighten the automatic

Looking for the young person in your life to have the best summer ever?. Check out the amazing summer camps and activities

Comparing the MCCA to Michigan’s auto insurance market as a whole thus reveals that catastrophic losses account for only for 1 to 2 percent of no-fault claims by

Wikimedia commons has warrants converse county missouri license in person is missouri property tax personal receipt.. Click on

The Kargil Review Committee, constituted after the 1991 Pakistan attack in the Kargil area, had expressed concern about the security and safety of land borders;

Overall, therefore, concomitant dysfunction in a number of brain networks involved in visual perception, inhibitory control and arousal may all play a role in the generation of