/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.userguide.sql;
import java.sql.Statement;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.annotations.Loader;
import org.hibernate.annotations.ResultCheckStyle;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLInsert;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.RequiresDialect;
import org.junit.Before;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNull;
/**
* @author Vlad Mihalcea
*/
@RequiresDialect(H2Dialect.class)
@RequiresDialect(PostgreSQL82Dialect.class)
public class CustomSQLSecondaryTableTest extends BaseEntityManagerFunctionalTestCase {
private static final Logger log = Logger.getLogger( CustomSQLSecondaryTableTest.class );
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Person.class
};
}
@Before
public void init() {
doInJPA( this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap( Session.class );
session.doWork( connection -> {
try(Statement statement = connection.createStatement(); ) {
statement.executeUpdate( "ALTER TABLE person ADD COLUMN valid boolean" );
statement.executeUpdate( "ALTER TABLE person_details ADD COLUMN valid boolean" );
}
} );
});
}
@Test
public void test_sql_custom_crud() {
Person _person = doInJPA( this::entityManagerFactory, entityManager -> {
Person person = new Person();
person.setName( "John Doe" );
entityManager.persist( person );
person.setImage( new byte[] {1, 2, 3} );
return person;
} );
doInJPA( this::entityManagerFactory, entityManager -> {
Long postId = _person.getId();
Person person = entityManager.find( Person.class, postId );
assertArrayEquals(new byte[] {1, 2, 3}, person.getImage());
entityManager.remove( person );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
Long postId = _person.getId();
Person person = entityManager.find( Person.class, postId );
assertNull(person);
} );
}
//tag::sql-custom-crud-secondary-table-example[]
@Entity(name = "Person")
@Table(name = "person")
@SQLInsert(
sql = "INSERT INTO person (name, id, valid) VALUES (?, ?, true) "
)
@SQLDelete(
sql = "UPDATE person SET valid = false WHERE id = ? "
)
@SecondaryTable(name = "person_details",
pkJoinColumns = @PrimaryKeyJoinColumn(name = "person_id"))
@org.hibernate.annotations.Table(
appliesTo = "person_details",
sqlInsert = @SQLInsert(
sql = "INSERT INTO person_details (image, person_id, valid) VALUES (?, ?, true) ",
check = ResultCheckStyle.COUNT
),
sqlDelete = @SQLDelete(
sql = "UPDATE person_details SET valid = false WHERE person_id = ? "
)
)
@Loader(namedQuery = "find_valid_person")
@NamedNativeQueries({
@NamedNativeQuery(
name = "find_valid_person",
query = "select " +
" p.id, " +
" p.name, " +
" pd.image " +
"from person p " +
"left outer join person_details pd on p.id = pd.person_id " +
"where p.id = ? and p.valid = true and pd.valid = true",
resultClass = Person.class
)
})
public static class Person {
@Id
@GeneratedValue
private Long id;
private String name;
@Column(name = "image", table = "person_details")
private byte[] image;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
}
//end::sql-custom-crud-secondary-table-example[]
}