/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.annotations.onetoone;
import java.util.Iterator;
import org.hibernate.EmptyInterceptor;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
import org.junit.Test;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.annotations.Customer;
import org.hibernate.test.annotations.Discount;
import org.hibernate.test.annotations.Passport;
import org.hibernate.test.annotations.Ticket;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Emmanuel Bernard
*/
public class OneToOneTest extends BaseCoreFunctionalTestCase {
@Test
public void testEagerFetching() throws Exception {
Session s;
Transaction tx;
s = openSession();
tx = s.beginTransaction();
Client c = new Client();
c.setName( "Emmanuel" );
Address a = new Address();
a.setCity( "Courbevoie" );
c.setAddress( a );
s.persist( c );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
Query q = s.createQuery( "select c from Client c where c.name = :name" );
q.setString( "name", c.getName() );
c = ( Client ) q.uniqueResult();
//c = (Client) s.get(Client.class, c.getId());
assertNotNull( c );
tx.commit();
s.close();
assertNotNull( c.getAddress() );
//assertTrue( "Should be eager fetched", Hibernate.isInitialized( c.getAddress() ) );
}
@Test
public void testDefaultOneToOne() throws Exception {
//test a default one to one and a mappedBy in the other side
Session s;
Transaction tx;
s = openSession();
tx = s.beginTransaction();
Customer c = new Customer();
c.setName( "Hibernatus" );
Passport p = new Passport();
p.setNumber( "123456789" );
s.persist( c ); //we need the id to assigned it to passport
c.setPassport( p );
p.setOwner( c );
p.setId( c.getId() );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
c = ( Customer ) s.get( Customer.class, c.getId() );
assertNotNull( c );
p = c.getPassport();
assertNotNull( p );
assertEquals( "123456789", p.getNumber() );
assertNotNull( p.getOwner() );
assertEquals( "Hibernatus", p.getOwner().getName() );
tx.commit(); // commit or rollback is the same, we don't care for read queries
s.close();
}
@Test
public void testOneToOneWithExplicitFk() throws Exception {
Client c = new Client();
Address a = new Address();
a.setCity( "Paris" );
c.setName( "Emmanuel" );
c.setAddress( a );
Session s;
Transaction tx;
s = openSession();
tx = s.beginTransaction();
s.persist( c );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
c = ( Client ) s.get( Client.class, c.getId() );
assertNotNull( c );
assertNotNull( c.getAddress() );
assertEquals( "Paris", c.getAddress().getCity() );
tx.commit();
s.close();
}
@Test
public void testOneToOneWithExplicitSecondaryTableFk() throws Exception {
Client c = new Client();
Address a = new Address();
a.setCity( "Paris" );
c.setName( "Emmanuel" );
c.setSecondaryAddress( a );
Session s;
Transaction tx;
s = openSession();
tx = s.beginTransaction();
s.persist( c );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
c = ( Client ) s.get( Client.class, c.getId() );
assertNotNull( c );
assertNotNull( c.getSecondaryAddress() );
assertEquals( "Paris", c.getSecondaryAddress().getCity() );
tx.commit();
s.close();
}
@Test
public void testUnidirectionalTrueOneToOne() throws Exception {
Body b = new Body();
Heart h = new Heart();
b.setHeart( h );
b.setId( 1 );
h.setId( b.getId() ); //same PK
Session s;
Transaction tx;
s = openSession();
tx = s.beginTransaction();
s.persist( h );
s.persist( b );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
b = ( Body ) s.get( Body.class, b.getId() );
assertNotNull( b );
assertNotNull( b.getHeart() );
assertEquals( h.getId(), b.getHeart().getId() );
tx.commit();
s.close();
}
@Test
public void testCompositePk() throws Exception {
Session s;
Transaction tx;
s = openSession();
tx = s.beginTransaction();
ComputerPk cid = new ComputerPk();
cid.setBrand( "IBM" );
cid.setModel( "ThinkPad" );
Computer c = new Computer();
c.setId( cid );
c.setCpu( "2 GHz" );
SerialNumberPk sid = new SerialNumberPk();
sid.setBrand( cid.getBrand() );
sid.setModel( cid.getModel() );
SerialNumber sn = new SerialNumber();
sn.setId( sid );
sn.setValue( "REZREZ23424" );
c.setSerial( sn );
s.persist( c );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
c = ( Computer ) s.get( Computer.class, cid );
assertNotNull( c );
assertNotNull( c.getSerial() );
assertEquals( sn.getValue(), c.getSerial().getValue() );
tx.commit();
s.close();
}
@Test
public void testBidirectionalTrueOneToOne() throws Exception {
Session s = openSession();
s.getTransaction().begin();
Party party = new Party();
PartyAffiliate affiliate = new PartyAffiliate();
affiliate.partyId = "id";
party.partyId = "id";
party.partyAffiliate = affiliate;
affiliate.party = party;
s.persist( party );
s.getTransaction().commit();
s.clear();
Transaction tx = s.beginTransaction();
affiliate = ( PartyAffiliate ) s.get( PartyAffiliate.class, "id" );
assertNotNull( affiliate.party );
assertEquals( affiliate.partyId, affiliate.party.partyId );
s.clear();
party = ( Party ) s.get( Party.class, "id" );
assertNotNull( party.partyAffiliate );
assertEquals( party.partyId, party.partyAffiliate.partyId );
s.delete( party );
s.delete( party.partyAffiliate );
tx.commit();
s.close();
}
@Test
public void testBidirectionalFkOneToOne() throws Exception {
Session s = openSession();
s.getTransaction().begin();
Trousers trousers = new Trousers();
TrousersZip zip = new TrousersZip();
trousers.id = 1;
zip.id = 2;
trousers.zip = zip;
zip.trousers = trousers;
s.persist( trousers );
s.persist( zip );
s.getTransaction().commit();
s.clear();
Transaction tx = s.beginTransaction();
trousers = ( Trousers ) s.get( Trousers.class, trousers.id );
assertNotNull( trousers.zip );
assertEquals( zip.id, trousers.zip.id );
s.clear();
zip = ( TrousersZip ) s.get( TrousersZip.class, zip.id );
assertNotNull( zip.trousers );
assertEquals( trousers.id, zip.trousers.id );
s.delete( zip );
s.delete( zip.trousers );
tx.commit();
s.close();
}
@Test
public void testForeignGenerator() {
Session s = openSession();
Transaction tx = s.beginTransaction();
Owner owner = new Owner();
OwnerAddress address = new OwnerAddress();
owner.setAddress( address );
address.setOwner( owner );
s.persist( owner );
s.flush();
s.clear();
owner = ( Owner ) s.get( Owner.class, owner.getId() );
assertNotNull( owner );
assertNotNull( owner.getAddress() );
assertEquals( owner.getId(), owner.getAddress().getId() );
tx.rollback();
s.close();
}
@Test
@TestForIssue( jiraKey = "HHH-4606" )
public void testJoinColumnConfiguredInXml() {
PersistentClass pc = configuration().getClassMapping( Son.class.getName() );
Iterator iter = pc.getJoinIterator();
Table table = ( ( Join ) iter.next() ).getTable();
Iterator columnIter = table.getColumnIterator();
boolean fooFound = false;
boolean barFound = false;
while ( columnIter.hasNext() ) {
Column column = ( Column ) columnIter.next();
if ( column.getName().equals( "foo" ) ) {
fooFound = true;
}
if ( column.getName().equals( "bar" ) ) {
barFound = true;
}
}
assertTrue(
"The mapping defines join columns which could not be found in the metadata.", fooFound && barFound
);
}
@Test
@FailureExpected( jiraKey = "HHH-6723" )
public void testPkOneToOneSelectStatementDoesNotGenerateExtraJoin() {
// This test uses an interceptor to verify that correct number of joins are generated.
Session s = openSession(new JoinCounter(1));
Transaction tx = s.beginTransaction();
Owner owner = new Owner();
OwnerAddress address = new OwnerAddress();
owner.setAddress( address );
address.setOwner( owner );
s.persist( owner );
s.flush();
s.clear();
owner = ( Owner ) s.get( Owner.class, owner.getId() );
assertNotNull( owner );
assertNotNull( owner.getAddress() );
assertEquals( owner.getId(), owner.getAddress().getId() );
s.flush();
s.clear();
address = ( OwnerAddress ) s.get( OwnerAddress.class, address.getId() );
assertNotNull( address );
assertNotNull( address.getOwner() );
assertEquals( address.getId(), address.getOwner().getId() );
s.flush();
s.clear();
owner = ( Owner ) s.createCriteria( Owner.class )
.add( Restrictions.idEq( owner.getId() ) )
.uniqueResult();
assertNotNull( owner );
assertNotNull( owner.getAddress() );
assertEquals( owner.getId(), owner.getAddress().getId() );
s.flush();
s.clear();
address = ( OwnerAddress ) s.createCriteria( OwnerAddress.class )
.add( Restrictions.idEq( address.getId() ) )
.uniqueResult();
address = ( OwnerAddress ) s.get( OwnerAddress.class, address.getId() );
assertNotNull( address );
assertNotNull( address.getOwner() );
assertEquals( address.getId(), address.getOwner().getId() );
s.flush();
s.clear();
tx.rollback();
s.close();
}
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
PartyAffiliate.class,
Party.class,
Trousers.class,
TrousersZip.class,
Customer.class,
Ticket.class,
Discount.class,
Passport.class,
Client.class,
Address.class,
Computer.class,
SerialNumber.class,
Body.class,
Heart.class,
Owner.class,
OwnerAddress.class
};
}
@Override
protected String[] getXmlFiles() {
return new String[] { "org/hibernate/test/annotations/onetoone/orm.xml" };
}
}
/**
* Verifies that generated 'select' statement has desired number of joins
* @author Sharath Reddy
*
*/
class JoinCounter extends EmptyInterceptor {
private static final long serialVersionUID = -3689681272273261051L;
private int expectedNumberOfJoins = 0;
public JoinCounter(int val) {
super();
this.expectedNumberOfJoins = val;
}
public String onPrepareStatement(String sql) {
int numberOfJoins = 0;
if (sql.startsWith("select") & !sql.contains("nextval")) {
numberOfJoins = count(sql, "join");
assertEquals( expectedNumberOfJoins, numberOfJoins );
}
return sql;
}
/**
* Count the number of instances of substring within a string.
*
* @param string String to look for substring in.
* @param substring Sub-string to look for.
* @return Count of substrings in string.
*/
private int count(final String string, final String substring)
{
int count = 0;
int idx = 0;
while ((idx = string.indexOf(substring, idx)) != -1)
{
idx++;
count++;
}
return count;
}
}