class T1 extends T {}
class T2 extends T {}
class T {
public static int i;
}
public class Test {
public static void main(String[] args) {
T1.i = 5;
T2.i = 3;
System.out.format("%d = %d", T1.i, T2.i);
}
}
/**
* Output: 3 = 3
*/
четверг, 1 декабря 2011 г.
Статические поля родителей являются общими для наследников
Избегать конкатенации строк оператором +
Избегать конкатенации строк оператором +. При каждом использовании данного оператора создается новый объект.
Long l1 = System.currentTimeMillis();
String test = new String();
for (int i = 0; i < 100000; i++) {
test += "d";
}
System.out.println(System.currentTimeMillis()-l1);
Long l2 = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append("d");
}
System.out.println(System.currentTimeMillis()-l2);
/**
* Output:
* 10728
* 10
*/
Использование нестатических блоков инициализации
При помощи нестатических блоков инициализации можно элегантно инициализировать коллекцию:
Map map = new HashMap() {{
put("собака", "барбос");
put("попугай", "кеша");
put("кошка", "мурка");
}};
Static methods cannot be overriden
В Java статические методы не могут быть переопределены наследниками
Сериализация
При десериализации не вызывается конструктор дессириализуемого класса, но если его родители не реализуют интерфейс Serializable, то у них вызывается конструктор по умолчанию.
java.io.NotSerializableException выбрасываться не будет в случае B b = null, т.к. объект не был инициализирован.
java.io.NotSerializableException выбрасываться не будет в случае B b = null, т.к. объект не был инициализирован.
public class Test {
public static void main(String[] args) throws FileNotFoundException,
IOException, ClassNotFoundException {
ObjectOutputStream out =
new ObjectOutputStream(new FileOutputStream("testfile"));
out.writeObject(new C(1));
ObjectInputStream in =
new ObjectInputStream(new FileInputStream("testfile"));
in.readObject();
}
}
class B {
public B() {
System.out.print("B");
}
public B(int i) {
System.out.print("1");
}
}
class C extends B implements Serializable {
B b = null;
public C() {
System.out.print("C");
}
public C(int i) {
super(i);
System.out.print("2");
}
}
/**
* Output: 12B
*/
четверг, 20 октября 2011 г.
Паттерн Декоратор (Decorator). Пример кода
public interface Car {
public int getPrice();
public String getDescription();
}
public class SimpleCar implements Car {
@Override
public int getPrice() {
return 100000;
}
@Override
public String getDescription() {
return "Simple auto";
}
}
public abstract class CarDecorator implements Car {
protected final Car car;
public CarDecorator(Car car) {
this.car = car;
}
@Override
public int getPrice() {
return car.getPrice();
}
@Override
public String getDescription() {
return car.getDescription();
}
}
public class Conditioner extends CarDecorator {
public Conditioner(Car car) {
super(car);
}
public int getPrice() {
return car.getPrice() + 2000;
}
public String getDescription() {
return car.getDescription() + " with conditioner";
}
}
public class LeatherInterior extends CarDecorator {
public LeatherInterior(Car car) {
super(car);
}
public int getPrice() {
return car.getPrice() + 3000;
}
public String getDescription() {
return car.getDescription() + " with leather interior";
}
}
public class Client {
public static void main(String[] args) {
Car car = new SimpleCar();
System.out.println("Price: " + car.getPrice()
+ ", Description: " + car.getDescription());
car = new Conditioner(car);
System.out.println("Price: " + car.getPrice()
+ ", Description: " + car.getDescription());
car = new LeatherInterior(car);
System.out.println("Price: " + car.getPrice()
+ ", Description: " + car.getDescription());
}
}
/**
* Output:
* Price: 100000, Description: Simple auto
* Price: 102000, Description: Simple auto with conditioner
* Price: 105000, Description: Simple auto with conditioner with leather interior
*/
вторник, 11 октября 2011 г.
Паттерн Компоновщик (Composite). Пример кода
/**
* Component
*/
public abstract class TextPart {
protected List value = new ArrayList();
public String getValue() {
StringBuilder sb = new StringBuilder();
for (TextPart textPart : value) {
sb.append(textPart.getValue());
}
return sb.toString();
}
public void append(TextPart... textPart) {
for (TextPart part : textPart) {
value.add(part);
}
}
}
/**
* Composite
*/
public class Sentence extends TextPart {
public Sentence(TextPart... value) {
for (TextPart textPart : value) {
this.value.add(textPart);
}
}
}
/**
* Composite
*/
public class Paragraph extends Sentence {
public Paragraph(TextPart... value) {
super(value);
}
@Override
public String getValue() {
return " " + super.getValue() + "\n\n";
}
}
/**
* Leaf
*/
public class Symbol extends TextPart {
private char value;
public Symbol(char value) {
this.value = value;
}
@Override
public String getValue() {
return String.valueOf(value);
}
@Override
public void append(TextPart... textPart) {
throw new UnsupportedOperationException();
}
}
public class Client {
public static void main(String[] args) {
Sentence sentence1 = new Sentence(
new Symbol('H'),
new Symbol('e'),
new Symbol('l'),
new Symbol('l'),
new Symbol('o')
);
System.out.println(sentence1.getValue());
Sentence sentence2 = new Sentence(
new Symbol('w'),
new Symbol('o'),
new Symbol('r'),
new Symbol('l'),
new Symbol('d'),
new Symbol('!')
);
Sentence sentence3 = new Sentence(sentence1, new Symbol(' '), sentence2);
System.out.println(sentence3.getValue());
Paragraph paragraph = new Paragraph(sentence3, new Symbol(' '), sentence3);
System.out.println(paragraph.getValue());
}
}
/**
* Output:
* Hello
* Hello world!
* Hello world! Hello world!
*/
среда, 5 октября 2011 г.
Паттерн Мост (Bridge). Пример кода
public abstract class Animal {
AnimalImp animalImp;
public Animal(AnimalImp animalImp) {
this.animalImp = animalImp;
}
public void say() {
animalImp.say();
}
}
public class HappyAnimal extends Animal {
public HappyAnimal(AnimalImp animalImp) {
super(animalImp);
}
}
public interface AnimalImp {
public void say();
}
public class Cat implements AnimalImp {
public void say() {
System.out.println("Miaou! I'm a happy cat!");
}
}
public class Pig implements AnimalImp {
public void say() {
System.out.println("Groin-groin! I'm a happy pig!");
}
}
public class Rooster implements AnimalImp {
public void say() {
System.out.println("Cocorico! I'm a happy rooster!");
}
}
import java.util.ArrayList;
import java.util.List;
public class Client {
public static void main(String[] args) {
List happyAnimals = new ArrayList();
happyAnimals.add(new HappyAnimal(new Cat()));
happyAnimals.add(new HappyAnimal(new Pig()));
happyAnimals.add(new HappyAnimal(new Rooster()));
for (Animal animal: happyAnimals) {
animal.say();
}
}
}
/**
* Output:
* Miaou! I'm a happy cat!
* Groin-groin! I'm a happy pig!
* Cocorico! I'm a happy rooster!
*/
среда, 28 сентября 2011 г.
Паттерн Адаптер (Пример кода)
/**
* Adaptee
*/
public class Item {
private double position = 0.0;
/**
* Конструктор задает начальное положение элемента
* @param initialPosition
*/
public Item(double initialPosition) {
position = initialPosition;
System.out.printf("Now initial position is %.2f inches\n", initialPosition);
}
/**
* Перемещает объект на inches дюймов
* @param inches расстояние для перемещения в дюймах
*/
public void move(double inches) {
position +=inches;
if (inches > 0) {
System.out.printf("Move forward to %.2f inches\n", inches);
} else if (inches < 0) {
System.out.printf("Move backward to %.2f inches\n", Math.abs(inches));
} else {
System.out.println("Not moved");
}
}
/**
* Возвращает текущую позицию элемента
*/
public double getPosition() {
System.out.printf("Current position is %.2f inches\n", position);
return position;
}
}
/**
* Adapter
*/
public class ItemAdapter {
private Item item;
private static final double cmInInches = 2.54;
/**
* Конструктор принимает начальную позицию элемента в сантиметрах
*/
public ItemAdapter(double initialPosition) {
item = new Item(convertCmToInches(initialPosition));
System.out.printf("Now initial position is %.2f cm\n", initialPosition);
}
/**
* @param cm смещение в сантиметрах
*/
public void move(double cm) {
item.move(convertCmToInches(cm));
System.out.printf("Move item to %.2f cm\n", cm);
}
/**
* Возврашает текущую позицию в сантиметрах
*/
public double getPosition() {
double position = convertInchesToCm(item.getPosition());
System.out.printf("Current position is %.2f cm\n", position);
return position;
}
/**
* Конвертирует сантиметры в дюймы
*/
private double convertCmToInches(double cm) {
return cm/cmInInches;
}
/**
* Конвертирует дюймы в сантиметры
*/
private double convertInchesToCm(double inches) {
return inches*cmInInches;
}
}
public class Client {
public static void main(String[] args) {
ItemAdapter itemAdapter = new ItemAdapter(100.0);
itemAdapter.move(55.4);
itemAdapter.getPosition();
itemAdapter.move(-232.1);
itemAdapter.getPosition();
}
}
/**
* Output:
* Now initial position is 39,37 inches
* Now initial position is 100,00 cm
* Move forward to 21,81 inches
* Move item to 55,40 cm
* Current position is 61,18 inches
* Current position is 155,40 cm
* Move backward to 91,38 inches
* Move item to -232,10 cm
* Current position is -30,20 inches
* Current position is -76,70 cm
*/
четверг, 18 августа 2011 г.
Ленивая инициализация. Пример кода
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public final class Person {
private final int id;
private final String name;
private final Map knownPersons = new HashMap();
public Person(int id, String name) {
this.name = name;
this.id = id;
}
/**
* Метод возвращает объект персоны, с которой знакома данная персона
* Если персоны еще не знакомы, то текущая персона знакомится и запоминает
* В этом методе и есть весь смысл примера
*/
public Person getKnownPerson(int id) {
if (!knownPersons.containsKey(id)) {
knownPersons.put(id, new Person(id, getNameById(id)));
}
return knownPersons.get(id);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (knownPersons.size() > 0) {
Iterator iterator = knownPersons.keySet().iterator();
while (iterator.hasNext()) {
int key = iterator.next();
Person person = knownPersons.get(key);
sb.append(person.toString());
}
} else {
sb.append("no known persons");
}
return "Person [id=" + id + ", name=" + name + ", knownPersons="
+ sb + "]";
}
private String getNameById(int id) {
return id + "'s Name";
}
public static void main(String[] args) {
Person person1 = new Person(1, "Вася Петя");
Person person2 = person1.getKnownPerson(2);
Person person3 = person1.getKnownPerson(3);
System.out.println(person2.toString());
System.out.println(person3.toString());
System.out.println(person1.toString());
}
}
/**
* Output:
* Person [id=2, name=2's Name, knownPersons=no known persons]
* Person [id=3, name=3's Name, knownPersons=no known persons]
* Person [id=1, name=Вася Петя, knownPersons=
* Person [id=2,name=2's Name, knownPersons=no known persons]
* Person [id=3, name=3's Name, knownPersons=no known persons]
* ]
*/
четверг, 11 августа 2011 г.
Паттерн фабричный метод. Пример кода
//product
public interface MilkProduct {
String getName();
float getWeight();
}
//creator
//в абстрактном классе можно сделать процедуры по созданию продукта по умолчанию
//или какие-то общие действия
public abstract class MilkProductCreator {
abstract public MilkProduct getProduct();
}
//concrete product
public class Butter implements MilkProduct {
private float weight = 3.5f;
final private static String NAME = "Масло";
@Override
public float getWeight() {
return weight;
}
@Override
public String getName() {
return NAME;
}
}
//concrete product
public class SourCream implements MilkProduct {
private float weight = 1.3f;
final private static String NAME = "Сметана";
@Override
public float getWeight() {
return weight;
}
@Override
public String getName() {
return NAME;
}
}
//concrete creator
public class ButterCreator extends MilkProductCreator {
@Override
public MilkProduct getProduct() {
return new Butter();
}
}
//concrete creator
public class SourCreamCreator extends MilkProductCreator {
@Override
public MilkProduct getProduct() {
return new SourCream();
}
}
public class Application {
public static void main(String[] args) {
MilkProductCreator[] milkProductCreators = {
new ButterCreator(),
new SourCreamCreator()
};
for (MilkProductCreator milkProductCreator : milkProductCreators) {
MilkProduct milkProduct = milkProductCreator.getProduct();
System.out.printf(
"%s. Вес: %.1f кг\n",
milkProduct.getName(), milkProduct.getWeight()
);
}
}
}
/*
* Output:
* Сметана. Вес: 1,3 кг
* Масло. Вес: 3,5 кг
*/
понедельник, 8 августа 2011 г.
Паттерн Builder (Строитель). Пример кода
/**
* Интерфейс, описывающий части, из которых может состоять здание
* Методы специально не сделаны абстрактными, что бы иметь возможность
* не строить ненужные части здания
*/
public abstract class Builder {
public void buildFundament() {
}
public void buildFloor() {
}
public void buildRoof() {
}
public void buildBasement() {
}
abstract Object getBuilding();
}
public class FrameHouseBuilder extends Builder {
private FrameHouse fh = new FrameHouse();
public void buildFundament() {
fh.setPart("Фундамент. ");
}
public void buildFloor() {
fh.setPart("1 этаж. ");
}
public void buildRoof() {
fh.setPart("Двускатная крыша. ");
}
@Override
public FrameHouse getBuilding() {
return fh;
}
}
public class OfficeBuildingBuilder extends Builder {
private OfficeBuilding ob = new OfficeBuilding();
private int floors = 0;
public void buildFundament() {
ob.setPart("Фундамент. ");
}
public void buildBasement() {
ob.setPart("Подвал. ");
}
public void buildFloor() {
floors++;
ob.setPart(floors + " этаж. ");
}
public void buildRoof() {
ob.setPart("Плоская крыша. ");
}
@Override
public OfficeBuilding getBuilding() {
return ob;
}
}
public class FrameHouse {
private StringBuilder parts = new StringBuilder();
public void setPart(String part) {
parts.append(part);
}
public String getParts() {
return parts.toString();
}
}
public class OfficeBuilding {
private StringBuilder parts = new StringBuilder();
public void setPart(String part) {
parts.append(part);
}
public String getParts() {
return parts.toString();
}
}
/**
* Распорядитель. Собирает различные виды зданий
*/
public class Director {
public static FrameHouse getFrameHouse() {
FrameHouseBuilder fhb = new FrameHouseBuilder();
fhb.buildFundament();
fhb.buildFloor();
fhb.buildRoof();
return fhb.getBuilding();
}
public static OfficeBuilding getOfficeBuilding() {
OfficeBuildingBuilder fhb = new OfficeBuildingBuilder();
fhb.buildBasement();
fhb.buildFundament();
for (int i=0; i < 5; i++) {
fhb.buildFloor();
}
fhb.buildRoof();
return fhb.getBuilding();
}
}
public class Application {
public static void main(String[] args) {
FrameHouse fh = Director.getFrameHouse();
System.out.println(fh.getParts());
OfficeBuilding ob = Director.getOfficeBuilding();
System.out.println(ob.getParts());
}
}
/*
* Output:
* Фундамент. 1 этаж. Двускатная крыша.
* Подвал. Фундамент. 1 этаж. 2 этаж. 3 этаж. 4 этаж. 5 этаж. Плоская крыша.
*/
Абстрактная фабрика. Пример кода
public interface GuiFactory {
Button createButton();
Checkbox createCheckbox();
}
public interface Button extends Cloneable {
void click();
Button clone();
}
public interface Checkbox extends Cloneable {
void check();
Checkbox clone();
}
public class NixButton implements Button {
@Override
public void click() {
System.out.println("NixButton clicked");
}
@Override
public Button clone() {
return new NixButton();
}
}
public class WinButton implements Button {
@Override
public void click() {
System.out.println("WinButton clicked");
}
@Override
public Button clone() {
return new WinButton();
}
}
public class NixCheckbox implements Checkbox {
@Override
public void check() {
System.out.println("NixCheckbox checked");
}
@Override
public Checkbox clone() {
return new NixCheckbox();
}
}
public class WinCheckbox implements Checkbox {
@Override
public void check() {
System.out.println("WinCheckbox checked");
}
@Override
public Checkbox clone() {
return new WinCheckbox();
}
}
public class NixGuiFactory implements GuiFactory{
@Override
public Button createButton() {
return new NixButton();
}
@Override
public Checkbox createCheckbox() {
return new NixCheckbox();
}
}
public class WinGuiFactory implements GuiFactory {
@Override
public Button createButton() {
return new WinButton();
}
@Override
public Checkbox createCheckbox() {
return new WinCheckbox();
}
}
public enum GuiTypes {
WIN, NIX
}
final public class GuiCreator {
final Button button;
final Checkbox checkbox;
public GuiCreator(GuiFactory factory) {
button = factory.createButton();
checkbox = factory.createCheckbox();
}
public Button getNewButton() {
return button.clone();
}
public Checkbox getNewCheckbox() {
return checkbox.clone();
}
}
public class Application {
public static void main(String args[]) {
GuiTypes guiType = GuiTypes.WIN;
GuiFactory factory = null;
switch (guiType) {
case NIX:
factory = new NixGuiFactory();
break;
case WIN:
factory = new WinGuiFactory();
break;
default:
throw new IllegalStateException();
}
GuiCreator guiCreator = new GuiCreator(factory);
Button button = guiCreator.getNewButton();
Checkbox checkbox = guiCreator.getNewCheckbox();
button.click();
checkbox.check();
}
}
Делегирование. Пример кода
public class Hands {
public void chop() {
System.out.println("Рубить");
}
}
public class Legs {
public void jump() {
System.out.println("Прыгать");
}
}
public class Man {
private Hands hands = new Hands();
private Legs legs = new Legs();
public void chop() {
hands.chop();
}
public void jump() {
legs.jump();
}
}
пятница, 5 августа 2011 г.
Immutable-класс. Пример кода
Решил, что буду в метро, вместо творческой литературы изучать шаблоны проектирования, а что бы лучше усвоился материал, писать потом по памяти свой пример. Описание паттернов выкладывать не буду, только код.
import java.util.Date;
public final class ImmutableTest {
private final String name;
private final Date dateOfBirth;
private final String[] skills;
public ImmutableTest(String name, Date dateOfBirth, String... skills) {
this.name = name;
/*при конструировании объекта, полям присваиваются новые объекты,
*вместо ссылок
*/
this.dateOfBirth = new Date(dateOfBirth.getTime());
this.skills = skills.clone();
}
public String getName() {
return name;
}
/*
* Возвращаем новый объект Date, вместо передачи ссылки на текущий
*/
public Date getDateOfBirth() {
return new Date(dateOfBirth.getTime());
}
/*
* Возвращаем клонированный массив, вместо ссылки на объект массива
*/
public String[] getSkills() {
return skills.clone();
}
}
понедельник, 1 августа 2011 г.
Работа с Java в командной строке
Нашел отличную статью про работу с Java в командной строке. http://habrahabr.ru/blogs/java/125210/
четверг, 28 июля 2011 г.
Транзакции, управляемые приложением
В предыдущем посте я писал про транзакции, которые управляются контейнером EJB. Сейчас я продолжаю знакомство с транзакциями и выкладываю свои заметки про транзакции, управляемые приложением.
Транзакции, управляемые контейнером имеют одно ограничение - когда метод запускается, он может быть ассоциирован только с одной транзакцией или без транзакций вовсе. Если требуется иное, имеет смысл использовать транзакции, управляемые бином (bean-managed transactions).
Когда транзакции находятся под управлением приложения, можно использовать JDBC или JTA-транзакции.
JTA-транзакции позволяют работать с базами данных разных производителей. JTA-транзакции не поддерживают вложенных транзакций, т.е. нельзя стартовать новую транзакцию, пока не завершилась другая.
Для управления транзакциями используются следующие методы: begin, commit и rollback. В JDBC-транзакции метод begin опускается, т.к. Подразумевается, что транзакция стартовала перед началом работы с БД.
Метод stateless session бина должен завершить транзакцию до того, как вернет результат, в то время как stateful session bean может сохранять состояние транзакции между обращениями клиента к методу. Даже если клиент закрывал и заново открывал соединение с БД, транзакция будет существовать до тех пор, пока не будет вызван метод commit или rollback.
Если stateful session bean использует JDBC-транзакцию, то её состояние так же может сохраняться между вызовами пользователя за тем исключением, что если jdbc-соединение будет закрыто - транзакция оборвется.
В транзакциях, управляемых приложением нельзя запускать методы управления транзакциями уровня контейнера getRollbackOnly и setRollbackOnly интерфейса EJBContext. Вместо этого надо использовать методы getStatus и rollback интерфейса UserTransaction.
Пример JDBC-транзакции:
Таймаут транзакций под управлением EBJ-контейнера выставляется сервером приложений, а транзакций под управлением приложением - методом setTransactionTimeout интерфейса UserTransaction. По умолчанию таймаут равен нулю, что значит, что он никогда не наступит.
Транзакции, управляемые контейнером имеют одно ограничение - когда метод запускается, он может быть ассоциирован только с одной транзакцией или без транзакций вовсе. Если требуется иное, имеет смысл использовать транзакции, управляемые бином (bean-managed transactions).
Когда транзакции находятся под управлением приложения, можно использовать JDBC или JTA-транзакции.
JTA-транзакции позволяют работать с базами данных разных производителей. JTA-транзакции не поддерживают вложенных транзакций, т.е. нельзя стартовать новую транзакцию, пока не завершилась другая.
Для управления транзакциями используются следующие методы: begin, commit и rollback. В JDBC-транзакции метод begin опускается, т.к. Подразумевается, что транзакция стартовала перед началом работы с БД.
Метод stateless session бина должен завершить транзакцию до того, как вернет результат, в то время как stateful session bean может сохранять состояние транзакции между обращениями клиента к методу. Даже если клиент закрывал и заново открывал соединение с БД, транзакция будет существовать до тех пор, пока не будет вызван метод commit или rollback.
Если stateful session bean использует JDBC-транзакцию, то её состояние так же может сохраняться между вызовами пользователя за тем исключением, что если jdbc-соединение будет закрыто - транзакция оборвется.
В транзакциях, управляемых приложением нельзя запускать методы управления транзакциями уровня контейнера getRollbackOnly и setRollbackOnly интерфейса EJBContext. Вместо этого надо использовать методы getStatus и rollback интерфейса UserTransaction.
Пример JDBC-транзакции:
public void ship (String productId, String orderId, int quantity) {Пример JTA-транзакции:
try {
con.setAutoCommit(false);
updateOrderItem(productId, orderId);
updateInventory(productId, quantity);
con.commit();
} catch (Exception ex) {
try {
con.rollback();
throw new EJBException("Transaction failed:" +
ex.getMessage());
} catch (SQLException sqx) {
throw new EJBException("Rollback failed:" +
sqx.getMessage());
}
}
}
public void withdrawCash(double amount) {
UserTransaction ut = context.getUserTransaction();
try {
ut.begin();
updateChecking(amount);
machineBalance -= amount;
insertMachine(machineBalance);
ut.commit();
} catch (Exception ex) {
try {
ut.rollback();
} catch (SystemException syex) {
throw new EJBException ("Rollback failed:" + syex.getMessage());
}
throw new EJBException ("Transaction failed:" + ex.getMessage());
}
}
Таймаут транзакций под управлением EBJ-контейнера выставляется сервером приложений, а транзакций под управлением приложением - методом setTransactionTimeout интерфейса UserTransaction. По умолчанию таймаут равен нулю, что значит, что он никогда не наступит.
Транзакции, управляемые контейнером EJB.
Enterprise beans поддерживают два типа управления транцакциями: container-managed или bean-managed. По умолчанию, если явно не задано, то используется первый, с которым я сегодня разбирался и хочу рассказать.
По сути, это просто заметки, сделанные с документации Java EE 6 Tutorial.
Container-managed транзакции упрощают разработку, т.к. за границами транзакции следит контейнер EJB. Транзакции, управляемые контейнером, могут работать как с session, так и с message-driven бинами.
Транзакция автоматически стартует перед началом запуска метода в бине и заканчивается по завершении этого метода. Container-managed транзакции не поддерживают вложенные и мульти-транзакции.
Container-managed транзакция не должна использовать методы управления транзакциями, т. к. эти операции возложены на контейнер EJB.
Существует возможность управления запуском транзакций для ejb-методов. Если внутри транцакции вызывается метод другого бина, то как должна вести себя транзакция с этим методом? На этот метод можно поставить различные ограничители принадлежности к текущей транзакции, при помощи аннотации @TransactionAttribute:
Пример:
в container-managed транзакциях существуют запрещенные методы, т.к. могут пересекаться с границами текущей транзакции:
По сути, это просто заметки, сделанные с документации Java EE 6 Tutorial.
Container-managed транзакции упрощают разработку, т.к. за границами транзакции следит контейнер EJB. Транзакции, управляемые контейнером, могут работать как с session, так и с message-driven бинами.
Транзакция автоматически стартует перед началом запуска метода в бине и заканчивается по завершении этого метода. Container-managed транзакции не поддерживают вложенные и мульти-транзакции.
Container-managed транзакция не должна использовать методы управления транзакциями, т. к. эти операции возложены на контейнер EJB.
Существует возможность управления запуском транзакций для ejb-методов. Если внутри транцакции вызывается метод другого бина, то как должна вести себя транзакция с этим методом? На этот метод можно поставить различные ограничители принадлежности к текущей транзакции, при помощи аннотации @TransactionAttribute:
- REQUIRED - если метод запущен внутри транзакции, то он является частью транзакции. Если запущен вне транзакции, то в нем стартует новая транзакция.
- REQUIRES_NEW - если метод запускается внутри транзакции, то она останавливается, запускается новая, отрабатывается, а затем продолжает работу первая. Если метод запускается самостоятельно, то просто стартует новая транзакция. Данный модификатор служит для того, что бы быть уверенным, что всегда будет запущена новая транзакция.
- MANDATORY - если метод запущен внутри транзакции, то он является её частью. Если же запускается вне транзакции, то бросается исключение TransactionRequiredException.
- NOT_SUPPORTED - если метод запускается внутри транзакции, то на время работы метода транзакция останавливается, пока не отработается метод, травзакция в которм не стартуетс, затем транзакция продолжает работу. Если метод запускается вне транзакции, то транзакция в нем не стартует. Этот атрибут увеличивает производительность, т.к. транзакции связаны с дополнительными нагрузками.
- SUPPORTS - если внутри транзакции, то является частью транзакции, если запускается самостоятельно, то транзакция не стартует.
- NEVER - Если внутри транзакции, то бросается исключение RemoteException, если вне транзакции, то метод запускается без старта транзакции.
Пример:
@TransactionAttribute(NOT_SUPPORTED)Если во время работы транзакции бросается системное исключение, то автоматом происходит откат транзакции. Управление откатом при эксепшенах приложения задается в методе setRollbackOnly интерфейса EJBContext, который обрабатывается с REQUIRED, REQUIRES_NEW, или MANDATORY атрибутами транзакции. Если данный метод не будет запущен — транзакция завершится успешно:
@Stateful
public class TransactionBean implements Transaction {
...
@TransactionAttribute(REQUIRES_NEW)
public void firstMethod() {...}
@TransactionAttribute(REQUIRED)
public void secondMethod() {...}
public void thirdMethod() {...}
public void fourthMethod() {...}
}
public void transferToSaving(double amount) throwsSession Beans поддерживают не обязательный интерфейс SessionSynchronization, который позволяет автоматически запускать методы на разных этапах выполнения транзакции: afterBegin, beforeCompletion, and afterCompletion. Первый может уведомлять сущность, что транзакция стартовала, второй запускается перед коммитом - последняя возможность сделать роллбек. Третий уведомляет, что транзакция выполнена и имеет только один булевый параметр со значением - true, если транзакция закоммичена или если роллбек - false
InsufficientBalanceException {
checkingBalance -= amount;
savingBalance += amount;
try {
updateChecking(checkingBalance);
if (checkingBalance < 0.00) {
context.setRollbackOnly();
throw new InsufficientBalanceException();
}
updateSaving(savingBalance);
} catch (SQLException ex) {
throw new EJBException
("Transaction failed due to SQLException: "
+ ex.getMessage());
}
}
в container-managed транзакциях существуют запрещенные методы, т.к. могут пересекаться с границами текущей транзакции:
- commit, setAutoCommit, и rollback методы класса java.sql.Connection
- getUserTransaction метод класса javax.ejb.EJBContext
- любой метод класса javax.transaction.UserTransaction
понедельник, 25 июля 2011 г.
Создавайте объекты только тогда, когда это необходимо
Создавать объекты надо только тогда, когда это действительно необходимо. Т.к. создание объекта является дорогостоящей операцией в плане производительности и освобождении памяти. В качестве решения проблемы можно использовать ленивую инициализацию:
public class Messages {
private List<String> messages;
public List<String> getMessages () {
if(messages == null) {
messages = new ArrayList<String>();
}
return messages;
}
}
Подписаться на:
Сообщения (Atom)