Have you commit something by mistake and also pushed everything?
git log
for the list of your log.
The log output is something like:
commit d946591753539639548b94b6aa40a875ce09a872
Author: Andrea Boriero <dreborier@gmail.com>
Date: Fri Nov 4 12:00:38 2011 +0000
bla bla bla
commit d946591753539639548b94b6aa40a875ce09a872
Author: Andrea Boriero <dreborier@gmail.com>
Date: Fri Nov 4 12:00:38 2011 +0000
bla bla bla
choose the commit you want to revert back, for example d946591753539639548b94b6aa40a875ce09a872
than to remove all commits after that:
git reset -f --hard d946591753539639548b94b6aa40a875ce09a872
and than to remove from origin:
git push -f
Hope this can help someone.
venerdì 4 novembre 2011
martedì 20 settembre 2011
Git - List all not pushed commits
git log --branches --not --remotes=origin
shows commits that is not present on remote origin branch
venerdì 26 agosto 2011
Git - restore deleted but not committed files
You have deleted the file HelloWorld.java but not yet committed, if you want to restore it :
git checkout HEAD HelloWorld.java
git checkout HEAD HelloWorld.java
giovedì 25 agosto 2011
Git, undoing uncommitted changes
You have the staged file HelloWorld.java, you have modified it and staged those changes but then you want to unstage those changes :
git reset HEAD -- HelloWorld.java
You have a new file HelloWorld.java, you have added it to staged files but then you do not want to commit the new file:
git rm --cached HelloWorld.java
if you want to undo all changes:
git checkout
Be careful, git checkout removes all untracked changes and you can't recover those changes anymore (files never tracked by Git will be deleted).
git reset HEAD -- HelloWorld.java
You have a new file HelloWorld.java, you have added it to staged files but then you do not want to commit the new file:
git rm --cached HelloWorld.java
if you want to undo all changes:
git checkout
Be careful, git checkout removes all untracked changes and you can't recover those changes anymore (files never tracked by Git will be deleted).
mercoledì 17 agosto 2011
My personal imaginary interview with The Clean Coder book :-P
Me : I must know my code works but how can I know my code works?
Uncle Bob's book : That's easy. Test it. Test it again. Test it up. Test it down. Test it seven ways to Sunday!... and don't forget to automate your test.
Me: But isn't code hard to test, my code really is?
Uncle Bob's book: yes but only because that code has been designed to be hard to test.
Me: how can my code be designed to be easy to test?
Uncle Bob's book: the best way is to write your tests first, before you write the code that passes them (TDD).
Uncle Bob's book : That's easy. Test it. Test it again. Test it up. Test it down. Test it seven ways to Sunday!... and don't forget to automate your test.
Me: But isn't code hard to test, my code really is?
Uncle Bob's book: yes but only because that code has been designed to be hard to test.
Me: how can my code be designed to be easy to test?
Uncle Bob's book: the best way is to write your tests first, before you write the code that passes them (TDD).
domenica 7 agosto 2011
A very minimal guide to the tar command
to extract from an archive
- for .tar use tar -xvf [archiveName]
- for .tar.gz, .tgz use tar -xvzf [archivefile]
- for .tar.bz2, .tbz2, .tbz use tar -xvjf [archivefile]
- for .tar.Z than use tar -xvZf [archivefile}
to compress a folder or a list of files
- for .tar use tar -cvf [archiveName] [pathname ...]
- for .tar.gz, .tgz use tar -cvzf [archiveName] [pathname ...]
- for .tar.bz2, .tbz2, .tbz use tar -cvjf [archivename] [pathname ...]
- for .tar.Z use tar -cvZf [archivename] [pathname ...]
[pathname ...] can be the path of a folder or the path of a list of files you want to compress.
to see the content of an archive, without extracting:
- for .tar use tar -tvf [archiveName]
- for .tar.gz, .tgz use tar -tvzf [archivefile]
- for .tar.bz2, .tbz2, .tbz use tar -tvjf [archivefile]
- for .tar.Z use tar -tvZf [archivefile}
lunedì 4 luglio 2011
Mocks and Stubs
What's the difference?
I found a very interesting post on this argument Mocks Aren't Stubs
reading the post I have learned that Stubs use state verification while Mocks use behaviour verification.
In few words:
I also learned that classical TDD style uses real objects as much as possible and a Test Double only if it's awkward to use the real ones while a mockist TDD style will always use a mock for all objects except the one under test.
Another couple of things:
I found a very interesting post on this argument Mocks Aren't Stubs
reading the post I have learned that Stubs use state verification while Mocks use behaviour verification.
In few words:
- with a mock you expect your class calls some mock object methods which in turn will return a particular data, what you'll check is that the class under test will really call those methods.
- With a stub, you implement the real object methods your test will use, naturally the implementation will be very easy. Than you'll check the state of the stub is what you expect (so you need to write some extra methods to access stub instance variables). Stubs may also record information about calls.
I also learned that classical TDD style uses real objects as much as possible and a Test Double only if it's awkward to use the real ones while a mockist TDD style will always use a mock for all objects except the one under test.
Another couple of things:
- A Test Double is a generic term used for any kind of object used to replace the real one for testing purposes.
- Types of Test Doubles, other than stubs and Mock,s are Dummy objects that are passed around but never actually used, usually they are used just to fill parameter lists. Fake objects that have an implementation not suitable for production.
sabato 25 giugno 2011
Professionalism is all about taking responsibility - First : Do Not Harm to Function
I just started reading the new Uncle Bob's Book "The Clean Coder".
From the beginning it seems another great book.
Actually I'm reading the first chapter titled "Professionalism".
I completely agree with Bob when he write "professionalism is all about taking responsibility"
How do we take responsibility?
Uncle Bob says "First, Do Not Harm" :
He tell us that it's unprofessional to send to QA "code you aren't certain about".
YOU MUST KNOW IT WORKS and you have only a way to be sure it works:
From the beginning it seems another great book.
Actually I'm reading the first chapter titled "Professionalism".
I completely agree with Bob when he write "professionalism is all about taking responsibility"
How do we take responsibility?
Uncle Bob says "First, Do Not Harm" :
- do not harm to Function
- do not harm Structure
Do not harm to Function, by being responsible for your errors.
because the only way to not harm the function of our SW is not creating bugs therefore to be professional we must not create bugs .
You must apology for every bug QA or even worst users find.
But this is not enough, you have to struggle for decreasing your bug rate towards the asymptote of zero.... we know zero is impossible but this is not an excuse for not trying to be as close as possible to it.
because the only way to not harm the function of our SW is not creating bugs therefore to be professional we must not create bugs .
You must apology for every bug QA or even worst users find.
But this is not enough, you have to struggle for decreasing your bug rate towards the asymptote of zero.... we know zero is impossible but this is not an excuse for not trying to be as close as possible to it.
He tell us that it's unprofessional to send to QA "code you aren't certain about".
YOU MUST KNOW IT WORKS and you have only a way to be sure it works:
You have to Test it, Test it and Test it .
Uncle Bob demand, not only suggest, for 100% test coverage.
Naturally he tell us 100% is an asymptote as for 0 bugs.
He tell us that if code is hard to test the only reason is that "code has been designed to be hard to test" so "design your code to be easy to test".
Uncle Bob demand, not only suggest, for 100% test coverage.
Naturally he tell us 100% is an asymptote as for 0 bugs.
He tell us that if code is hard to test the only reason is that "code has been designed to be hard to test" so "design your code to be easy to test".
Uncle Bob naturally tell us which is the best way to design our code for easy testing, "write your test first".
Here ends the first part of the story, in a future post I will talk about the Uncle Bob advise on how Do Not Harm Structure.
This is only a very short and raw summary of the Do Not Harm to Function topic, the book is full of explanations, examples and great stories... so I can only say buy the Book The Clean Coder Book and start reading it, for me is a must.
A second advice is to visit The Clean Coders Web Site the videos are cheap and great.
A second advice is to visit The Clean Coders Web Site the videos are cheap and great.
giovedì 23 giugno 2011
goto statement - bad or not?
I just started reading some stuff about Go programming Language (http://golang.org/) and I discovered it supports the goto statement.
But goto statement is bad..... a good programming language should not have a goto statement or not????
So I started surfing the web trying to understand why smart guys like those at Google could create a new language with a goto and I found golang-nuts and than the Linus Torvalds opinion on this topic http://kerneltrap.org/node/553/2131.
I think it's worth reading.
But goto statement is bad..... a good programming language should not have a goto statement or not????
So I started surfing the web trying to understand why smart guys like those at Google could create a new language with a goto and I found golang-nuts and than the Linus Torvalds opinion on this topic http://kerneltrap.org/node/553/2131.
I think it's worth reading.
mercoledì 22 giugno 2011
Constant Interface Antipattern
I thought was a good practice to put static members into an interface and inherit from that interface.
But it's a very bad idea or even more an Antipattern : Constant Interface Antipattern (see Effective Java) .
Why is it so bad?
The use of static member from another class is an implementation details and interfaces are used to abstract from implementation details.
In other words:
The use of static member causes a leakage of implementation details into many unrelated classes, because any of the defined static constant will be available to all of your classes that implement this interface.
So remember:
Interfaces are for defining contracts, not for constants.
Why do you want to declare static members into an interface?
May be to avoid putting class names in front of constants while accessing them or to group related constants .
Solutions?
Put constants into class and use static import but Very sparingly!
Use only when you require frequent access to static members from one or two classes.
If you overuse the static import feature, it can make your program unreadable and unmaintainable, you not know which class a static member comes from but used appropriately, static import can make your code more readable, by removing the boilerplate of repetition of class names.
Interesting link :
http://download.oracle.com/javase/1,5.0/docs/guide/language/static-import.html
http://www.jroller.com/ksevindik/entry/some_thoughts_about_constant_interface
http://stackoverflow.com/questions/3547792/grouping-related-constants-shared-between-classes
But it's a very bad idea or even more an Antipattern : Constant Interface Antipattern (see Effective Java) .
Why is it so bad?
The use of static member from another class is an implementation details and interfaces are used to abstract from implementation details.
In other words:
The use of static member causes a leakage of implementation details into many unrelated classes, because any of the defined static constant will be available to all of your classes that implement this interface.
So remember:
Interfaces are for defining contracts, not for constants.
Why do you want to declare static members into an interface?
May be to avoid putting class names in front of constants while accessing them or to group related constants .
Solutions?
Put constants into class and use static import but Very sparingly!
Use only when you require frequent access to static members from one or two classes.
If you overuse the static import feature, it can make your program unreadable and unmaintainable, you not know which class a static member comes from but used appropriately, static import can make your code more readable, by removing the boilerplate of repetition of class names.
Interesting link :
http://download.oracle.com/javase/1,5.0/docs/guide/language/static-import.html
http://www.jroller.com/ksevindik/entry/some_thoughts_about_constant_interface
http://stackoverflow.com/questions/3547792/grouping-related-constants-shared-between-classes
sabato 18 giugno 2011
Linux - which program is using a device
There has never happened to not be able to unmount a device because of a message tells you some program is using it?
But which program?
The lsof command is what you need.
For example if I mount a device as /media/disk
typing lsof /media/disk I obtain the following result:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Thunar 1448 drea 20r DIR 8,16 32768 1 /
Thunar 1448 drea 21r DIR 8,16 32768 1 /media/disk
pretty useful information :-)
But which program?
The lsof command is what you need.
For example if I mount a device as /media/disk
typing lsof /media/disk I obtain the following result:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Thunar 1448 drea 20r DIR 8,16 32768 1 /
Thunar 1448 drea 21r DIR 8,16 32768 1 /media/disk
pretty useful information :-)
martedì 24 maggio 2011
GWT ToggleButton ActionCell
GWT with version 2.1 introduced Cell widgets, we can find CellList, CellTable, CellTree and CellBrowser and a lot of Cell Types : TextCell,EditTextCell, ButtonCell ... GWT Developerr's Guide, what I wasn't able to find is a ToggleButton Cell Type so I decided to implement my own version.
I called it ToggleButtonActionCell and the following is the code I wrote:
public class ToggleButtonActionCell<C> extends AbstractCell<C> {
private SelectionModel<C> selectionModel;
/**
* An html string representation of a pressed button.
*/
private static final SafeHtml TOGGLE_BUTTON_UP = SafeHtmlUtils
.fromSafeConstant("<button type=\"button\" class=\"toggleButton toggleButton-up\" tabindex=\"-1\" aria-pressed=\"true\">");
/**
* An html string representation of an unpressed.
*/
private static final SafeHtml TOGGLE_BUTTON_DOWN = SafeHtmlUtils
.fromSafeConstant("<button type=\"button\" class=\"toggleButton toggleButton-down\" tabindex=\"-1\" aria-pressed=\"false\">");
/**
* The delegate that will handle events from the cell.
*
* @param <T>
* the type that this delegate acts on
*/
public static interface Delegate<T> {
/**
* Perform the desired action on the given object.
*
* @param object
* the object to be acted upon
*/
void execute(T object, Boolean wasPressed);
}
private final SafeHtml upImage;
private final SafeHtml downImage;
protected final SafeHtml htmlPressed;
protected final SafeHtml htmlUnPpressed;
private final Delegate<C> delegate;
SafeHtmlBuilder sb;
public ToggleButtonActionCell(Image upImage, Image downImage,
SelectionModel<C> selectionModel, Delegate<C> delegate) {
super("click");
this.upImage = new SafeHtmlBuilder().appendHtmlConstant(
upImage.toString()).toSafeHtml();
this.downImage = new SafeHtmlBuilder().appendHtmlConstant(
downImage.toString()).toSafeHtml();
this.delegate = delegate;
this.htmlPressed = new SafeHtmlBuilder().append(TOGGLE_BUTTON_UP)
.append(this.downImage).appendHtmlConstant("</button>")
.toSafeHtml();
this.htmlUnPpressed = new SafeHtmlBuilder().append(TOGGLE_BUTTON_DOWN)
.append(this.upImage).appendHtmlConstant("</button>")
.toSafeHtml();
this.selectionModel = selectionModel;
}
@Override
public void render(Context context, C value, SafeHtmlBuilder sb) {
this.sb = sb;
if (selectionModel.isSelected(value)) {
sb.append(htmlPressed);
} else {
sb.append(htmlUnPpressed);
}
}
@Override
public void onBrowserEvent(Context context, Element parent, C value,
NativeEvent event, ValueUpdater<C> valueUpdater) {
if ("click".equals(event.getType())) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
onEnterKeyDown(context, parent, value, event, valueUpdater);
selectionModel.setSelected(value, !selectionModel.isSelected(value));
toggleButtonImage(parent, context,selectionModel.isSelected(value));
}
}
@Override
protected void onEnterKeyDown(Context context, Element parent, C value,
NativeEvent event, ValueUpdater<C> valueUpdater) {
delegate.execute(value, selectionModel.isSelected(value));
}
private void toggleButtonImage(Element parent, Context context, Boolean setPressed) {
com.google.gwt.user.client.Element button = getButton(parent);
if (setPressed) {
setPressed(button, true);
setButtonImage(button, downImage);
} else {
setPressed(button, false);
setButtonImage(button, upImage);
}
}
private void setPressed(com.google.gwt.user.client.Element button, boolean isPressed) {
DOM.setElementAttribute(button, "aria-pressed", Boolean.toString(isPressed));
if(isPressed){
DOM.setElementAttribute(button, "class", "toggleButton toggleButton-down");
}else{
DOM.setElementAttribute(button, "class", "toggleButton toggleButton-up");
}
}
private void setButtonImage(Element button, SafeHtml image) {
Element img = button.getFirstChildElement();
button.removeChild(img);
button.setInnerHTML(image.asString());
}
private com.google.gwt.user.client.Element getButton(Element parent) {
com.google.gwt.user.client.Element button = parent
.getFirstChildElement().cast();
return button;
}
}
I hope someone can find this code useful and any comment and suggestion is welcome.
I called it ToggleButtonActionCell and the following is the code I wrote:
public class ToggleButtonActionCell<C> extends AbstractCell<C> {
private SelectionModel<C> selectionModel;
/**
* An html string representation of a pressed button.
*/
private static final SafeHtml TOGGLE_BUTTON_UP = SafeHtmlUtils
.fromSafeConstant("<button type=\"button\" class=\"toggleButton toggleButton-up\" tabindex=\"-1\" aria-pressed=\"true\">");
/**
* An html string representation of an unpressed.
*/
private static final SafeHtml TOGGLE_BUTTON_DOWN = SafeHtmlUtils
.fromSafeConstant("<button type=\"button\" class=\"toggleButton toggleButton-down\" tabindex=\"-1\" aria-pressed=\"false\">");
/**
* The delegate that will handle events from the cell.
*
* @param <T>
* the type that this delegate acts on
*/
public static interface Delegate<T> {
/**
* Perform the desired action on the given object.
*
* @param object
* the object to be acted upon
*/
void execute(T object, Boolean wasPressed);
}
private final SafeHtml upImage;
private final SafeHtml downImage;
protected final SafeHtml htmlPressed;
protected final SafeHtml htmlUnPpressed;
private final Delegate<C> delegate;
SafeHtmlBuilder sb;
public ToggleButtonActionCell(Image upImage, Image downImage,
SelectionModel<C> selectionModel, Delegate<C> delegate) {
super("click");
this.upImage = new SafeHtmlBuilder().appendHtmlConstant(
upImage.toString()).toSafeHtml();
this.downImage = new SafeHtmlBuilder().appendHtmlConstant(
downImage.toString()).toSafeHtml();
this.delegate = delegate;
this.htmlPressed = new SafeHtmlBuilder().append(TOGGLE_BUTTON_UP)
.append(this.downImage).appendHtmlConstant("</button>")
.toSafeHtml();
this.htmlUnPpressed = new SafeHtmlBuilder().append(TOGGLE_BUTTON_DOWN)
.append(this.upImage).appendHtmlConstant("</button>")
.toSafeHtml();
this.selectionModel = selectionModel;
}
@Override
public void render(Context context, C value, SafeHtmlBuilder sb) {
this.sb = sb;
if (selectionModel.isSelected(value)) {
sb.append(htmlPressed);
} else {
sb.append(htmlUnPpressed);
}
}
@Override
public void onBrowserEvent(Context context, Element parent, C value,
NativeEvent event, ValueUpdater<C> valueUpdater) {
if ("click".equals(event.getType())) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
onEnterKeyDown(context, parent, value, event, valueUpdater);
selectionModel.setSelected(value, !selectionModel.isSelected(value));
toggleButtonImage(parent, context,selectionModel.isSelected(value));
}
}
@Override
protected void onEnterKeyDown(Context context, Element parent, C value,
NativeEvent event, ValueUpdater<C> valueUpdater) {
delegate.execute(value, selectionModel.isSelected(value));
}
private void toggleButtonImage(Element parent, Context context, Boolean setPressed) {
com.google.gwt.user.client.Element button = getButton(parent);
if (setPressed) {
setPressed(button, true);
setButtonImage(button, downImage);
} else {
setPressed(button, false);
setButtonImage(button, upImage);
}
}
private void setPressed(com.google.gwt.user.client.Element button, boolean isPressed) {
DOM.setElementAttribute(button, "aria-pressed", Boolean.toString(isPressed));
if(isPressed){
DOM.setElementAttribute(button, "class", "toggleButton toggleButton-down");
}else{
DOM.setElementAttribute(button, "class", "toggleButton toggleButton-up");
}
}
private void setButtonImage(Element button, SafeHtml image) {
Element img = button.getFirstChildElement();
button.removeChild(img);
button.setInnerHTML(image.asString());
}
private com.google.gwt.user.client.Element getButton(Element parent) {
com.google.gwt.user.client.Element button = parent
.getFirstChildElement().cast();
return button;
}
}
I hope someone can find this code useful and any comment and suggestion is welcome.
venerdì 22 aprile 2011
Linux how to generate a ssh key and copy it to a server
This morning I had to generate a key for a ssh connection to a remote machine where we have our remote internal git repository.
The first step is to generate the key using the command ssh-keygen -t rsa which prompt to enter the key file name, I typed ~/.ssh/id_rsa and to enter a passphrase (remember if you enter it you will be asked for it every time you want connect to the remote machine)
now in the folder ~/.ssh there are 2 files:
The first step is to generate the key using the command ssh-keygen -t rsa which prompt to enter the key file name, I typed ~/.ssh/id_rsa and to enter a passphrase (remember if you enter it you will be asked for it every time you want connect to the remote machine)
now in the folder ~/.ssh there are 2 files:
- id_rsa, the private key
- id_rsa.pub, the public key
The second step is to copy the public key to the remote machine, to do that use the command ssh-copy-id -i ~/.ssh/id_rsa.pub user@remote_machine
This is all.
In my case I had an old previous key with a differente name, I deleted it and so the ssh wasn't able to find my key. I discovered becouse every time I tryed to connect to the remote machine with ssh user@remote_machine my password (not my passphrase) was required. So I modified the /etc/ssh/ssh-config file
Host *IdentityFile ~/.ssh/id_rsa #the private key locationto use multiple private keys to connect to different servers check http://stackoverflow.com/questions/2419566/best-way-to-use-multiple-ssh-private-keys-on-one-client
giovedì 21 aprile 2011
Delete all svn directory quickly in linux
Sometimes I had the need to remove all .svn folders from a project, a friend of mine told me a quick and easy way (if you are so lucky to work on linux).
From mc (Midnight commander)
From mc (Midnight commander)
- navigate to the root folder of the project
- press F9 and choose from the menu bar Command --> Find File
- in the File name field enter .svn
- delete all from the Content field (leave it empty)
- press ok
- when the search end select the option Panelize ... all the finded folder will be shown in the classic mc directory panel
- select all with the insert keyboard button
- press F8
All the .svn folders will be removed.
I hope this will be useful for some novice linux user like me :-)
I hope this will be useful for some novice linux user like me :-)
A quick mc tutorial http://www.trembath.co.za/mctutorial.html
venerdì 25 marzo 2011
Hibernate load vs get
The load method returns a proxy and hits the database only when you access a filed of the entity. If any entity is found the load method throws an ObjectNotFounfException but only when you try to access the entity fields.
The get method hits the database as soon as it's called and if no entity is found returns null.
When to use get and when load?
The load method increases perfromance (hits the database only when necessary) so if you know your entity will be used only within the unit of work where it's retrieved than the load method is probably the best choice but if the retrieved entity is used outsite the transactional unit of work, e.g. it's displayed on a web page, using the get method is probably better.
The get method hits the database as soon as it's called and if no entity is found returns null.
When to use get and when load?
The load method increases perfromance (hits the database only when necessary) so if you know your entity will be used only within the unit of work where it's retrieved than the load method is probably the best choice but if the retrieved entity is used outsite the transactional unit of work, e.g. it's displayed on a web page, using the get method is probably better.
giovedì 24 marzo 2011
Hibernate HQL and fetch="join"
Mapping a relationship between two entities with fetch="join" has two different behaviours depending on the type of query.
public class Book {
private long id;
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getId() {
return id;
}
void setId(long id) {
this.id = id;
}
}
so books are loaded along with authors.
As an example if you have an entity Author
public class Author {
private long id;
private String name;
private Set books = new HashSet();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getBooks() {
return books;
}
public void setBooks(Set books) {
this.books = books;
}
public long getId() {
return id;
}
void setId(long id) {
this.id = id;
}
public void addBook(Book b){
books.add(b);
}
}
with his mapping file Author.hbm.xml :
<hibernate-mapping package="org.dreborier.domain"> <class name="Author" table="AUTHOR"> <id name="id" column="AUTHOR_ID"> <generator class="native"></generator> </id> <property name="name" column="NAME"></property> <set name="books" table="BOOK" cascade="save-update" fetch="join"> <key column="AUTHOR_ID"></key> <one-to-many class="Book"/> </set> </class> </hibernate-mapping>
and the entity Book :
public class Book {
private long id;
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getId() {
return id;
}
void setId(long id) {
this.id = id;
}
}
along with the mapping file Book.hbm.xml :
<hibernate-mapping package="org.dreborier.domain">
<class name="Book" table="BOOK">
<id name="id" column="BOOK_ID">
<generator class="native"></generator>
</id> <property name="title" column="TITLE"></property> </class>
</hibernate-mapping>
<class name="Book" table="BOOK">
<id name="id" column="BOOK_ID">
<generator class="native"></generator>
</id> <property name="title" column="TITLE"></property> </class>
</hibernate-mapping>
if you use a query by Criteria :
Criteria criteria = session.createCriteria(Author.class);
List authors = criteria.list();
List
with the fecth="join" attribute hibernate will execute the following query :
select this_.AUTHOR_ID as AUTHOR1_0_1_, this_.NAME as NAME0_1_, books2_.BOOK_ID as BOOK1_0_3_, books2_.BOOK_ID as BOOK1_3_, books2_.BOOK_ID as BOOK1_1_0_, books2_.TITLE as TITLE1_0_ from AUTHOR this_ left outer join BOOK books2_ on this_.AUTHOR_ID=books2_.BOOK_ID
so books are loaded along with authors.
while if you use HQL :
Query query = session.createQuery("from Author");
List authors = query.list();
List
hibernate will execute the following query:
select author0_.AUTHOR_ID as AUTHOR1_0_, author0_.NAME as NAME0_ from AUTHOR author0_
as you can see the fetch="join" do not affect the HQL query and a second query wiil be executed when an author's book is accessed
so if you want to fetch eagerly the Book using HQL you have to use left join fetch :
Query query = session.createQuery("from Author as author left join fetch author.books");
Hibernate Reference Documentation recommends
The following code:
select author0_.AUTHOR_ID as AUTHOR1_0_0_, author0_.NAME as NAME0_0_ from AUTHOR author0_ where author0_.AUTHOR_ID=?
and
select books0_.AUTHOR_ID as AUTHOR3_0_1_, books0_.BOOK_ID as BOOK1_1_, books0_.BOOK_ID as BOOK1_1_0_, books0_.TITLE as TITLE1_0_ from BOOK books0_ where books0_.AUTHOR_ID=?
while with fetch="join" the database is hit only one time
select author0_.AUTHOR_ID as AUTHOR1_0_1_, author0_.NAME as NAME0_1_, books1_.AUTHOR_ID as AUTHOR3_0_3_, books1_.BOOK_ID as BOOK1_3_, books1_.BOOK_ID as BOOK1_1_0_, books1_.TITLE as TITLE1_0_ from AUTHOR author0_ left outer join BOOK books1_ on author0_.AUTHOR_ID=books1_.AUTHOR_ID where author0_.AUTHOR_ID=?
as you can see the fetch="join" do not affect the HQL query and a second query wiil be executed when an author's book is accessed
so if you want to fetch eagerly the Book using HQL you have to use left join fetch :
Query query = session.createQuery("from Author as author left join fetch author.books");
Hibernate Reference Documentation recommends
Usually, the mapping document is not used to customize fetching. Instead, we keep the defaultbehavior, and override it for a particular transaction, using left join fetch in HQL. This tellsHibernate to fetch the association eagerly in the first select, using an outer join. In the Criteriaquery API, you would use setFetchMode(FetchMode.JOIN).The fetch="join" attibute defined in the mapping file affects get and load methods.
The following code:
Author author = (Author) session.get(Author.class, 1L);
Set books = author.getBooks();
books.size();
without the fetch attribute will produce two database hitsselect author0_.AUTHOR_ID as AUTHOR1_0_0_, author0_.NAME as NAME0_0_ from AUTHOR author0_ where author0_.AUTHOR_ID=?
and
select books0_.AUTHOR_ID as AUTHOR3_0_1_, books0_.BOOK_ID as BOOK1_1_, books0_.BOOK_ID as BOOK1_1_0_, books0_.TITLE as TITLE1_0_ from BOOK books0_ where books0_.AUTHOR_ID=?
while with fetch="join" the database is hit only one time
select author0_.AUTHOR_ID as AUTHOR1_0_1_, author0_.NAME as NAME0_1_, books1_.AUTHOR_ID as AUTHOR3_0_3_, books1_.BOOK_ID as BOOK1_3_, books1_.BOOK_ID as BOOK1_1_0_, books1_.TITLE as TITLE1_0_ from AUTHOR author0_ left outer join BOOK books1_ on author0_.AUTHOR_ID=books1_.AUTHOR_ID where author0_.AUTHOR_ID=?
Iscriviti a:
Commenti (Atom)