Hibernate callable attribute throwing error in #NamedNativeQuery in Hibernate 3.2.5 - oracle

May i know why callable not working in hibernate 3.2.5 inside #NamedNativeQuery and it throws compilation error. Can anyone know why it is throwing error and please let me know which version it will support.
I need to call oracle stored procedure from Hibernate entity class using #NamedNativeQuery . Please help.

I implemented like below and everything works fine.
Student.class
#Entity
#NamedNativeQueries(
#NamedNativeQuery(
name = Student.UPDATE,
query = "CALL updateStudent(:studentId, :studentName)",
)
)
public class Student extends ABaseEntity {
public static final String UPDATE = "Student.update";
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
updateStudent procedure
CREATE OR REPLACE PROCEDURE UPDATESTUDENT
(
studentId IN NUMBER
, studentName IN VARCHAR2
) AS
BEGIN
Update student set name = studentName where id = studentId;
END UPDATESTUDENT;
StudentDao
#Stateless
public class StudentDao {
#PersistenceContext(name = "tngo")
private EntityManager entityManager;
public void updateStudent(Long id, String name){
Query query = entityManager.createNamedQuery(Student.UPDATE);
query.setParameter("studentId", id);
query.setParameter("studentName", name);
query.executeUpdate();
}
}
I'm using jpa with hibernate provider version 5.1.0.Final. If you want to return result sets from procedure, you can provide resultClass and resultSetMapping in #NamedNativeQuery annotation.

Related

update all entries inside a SQL column with #PostPersit in Spring Boot

I'm trying to update automaticly all entries of a new sql column with the #PostPersist anotation.
the model :
int id;
String firstName;
String SecondName;
String Maths;
#AutoWired
ModelService modelService;
#PostPersist
public void setMathsWithPostPersist(){
if(Maths == null) {
Maths = modelService.calculate(id);
}
}
Then, here's the service:
public int calculateById(int id){
Model model = modelRepository.getById(id);
int number = calculateNumber(model);
model.setMaths(number);
modelRepository.save(organisme);
return number;
}
I don't know if it's due to the fact that I'm using an autowired in the model class, that's my first use of #PostPersist.
What did I do wrong?
The #PostPersist listener is only invoked when "persisting" an entity, but what you are doing here is an update of an existing entity, so you would have to use #PostUpdate instead.

Mockito Test for Spring NamedJDBC Template

I am trying to figure out mickito test for Named Jdbc Template but unable to do so. I did googling but did not find any accurate result. Below is example Code.
Student.class
#Data
public class Student {
private int id;
private String name;
private String address;
public Student(ResultSet rs) throws SQLException {
id = rs.getInt("id");
name = rs.getString("name");
address = rs.getString("address");
}
}
Student class takes ResultSet argument in constructor and mapped all column to variable .
StudentService.class
public class StudentService {
#Autowired
#Qualifier("namedJdbcTemplate")
NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public Student gerStudent(String id) {
Student student;
String selectStudent = "select id , name ,address from student where id=:id";
MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
mapSqlParameterSource.addValue(id, "id");
student = namedParameterJdbcTemplate.query(selectStudent, mapSqlParameterSource, resultSet -> {
Student response = new Student(resultSet);
return response;
});
return student;
}
}
Can anyone please help on Mockito Test for below line of code?
student = namedParameterJdbcTemplate.query(selectStudent, mapSqlParameterSource, resultSet -> {
Student response = new Student(resultSet);
return response;
});

Spring-Data-JPA atomic insert with dependencies

I want to insert Entities to a database from a scalable microservice. I tried #Lock(LockModeType.PESSIMISTIC_WRITE) to prevent from doubled entries. The problem is, I have dependencies on my Entities.
A basic example is:
TestEntity.java
public class TestEntity {
#GeneratedValue()
#Id
private Long id;
private String string;
#ManyToOne
private TestEntityParent testEntityParent;
}
TestEntityParent.java
public class TestEntityParent {
#GeneratedValue()
#Id
private Long id;
private String stringTwo;
#OneToMany(mappedBy = "testEntityParent")
private List<TestEntity> testEntities;
}
TestEnityRepository.java
public interface TestEnityRepository extends JpaRepository<TestEntity,Long> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
TestEntity saveAndFlush(TestEntity testEntity);
Optional<TestEntity> findByStringAndTestEntityParentStringTwo(String string, String stringTwo);
}
TestEntityParentRepository.java
public interface TestEntityParentRepository extends JpaRepository<TestEntityParent, Long> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
TestEntityParent save(TestEntityParent testEntityParent);
Optional<TestEntityParent> findByStringTwo(String stringTwo);
}
AtomicDbService.java
#Service
public class AtomicDbService {
#Autowired
TestEnityRepository testEnityRepository;
#Autowired
TestEntityParentRepository testEntityParentRepository;
#Transactional
public TestEntity atomicInsert(TestEntity testEntity) {
TestEntityParent testEntityParent = testEntityParentRepository.findByStringTwo(testEntity.getTestEntityParent().getStringTwo())
.orElse(testEntityParentRepository.save(testEntity.getTestEntityParent()));
return testEnityRepository.findByStringAndTestEntityParentStringTwo(
testEntity.getString(), testEntity.getTestEntityParent().getStringTwo()
).orElse(testEnityRepository
.save(
TestEntity.builder()
.string(testEntity.getString())
.testEntityParent(testEntityParent)
.build()
)
);
}
}
My test case:
#Test
#Transactional
public void testAtomicInsert(){
TestEntityParent testEntityParent = TestEntityParent.builder().stringTwo("testTwo").build();
TestEntity testEntity = TestEntity.builder().string("test").testEntityParent(testEntityParent).build();
atomicDbService.atomicInsert(testEntity);
System.out.println(testEnityRepository.findAll());
atomicDbService.atomicInsert(testEntity);
System.out.println(testEnityRepository.findAll());
atomicDbService.atomicInsert(testEntity);
System.out.println(testEnityRepository.findAll());
System.out.println(testEnityRepository.findAll());
}
I get the following answer:
[TestEntity(id=2, string=test, testEntityParent=TestEntityParent(id=1, stringTwo=testTwo, testEntities=null))]
[TestEntity(id=2, string=test, testEntityParent=TestEntityParent(id=1, stringTwo=testTwo, testEntities=null)), TestEntity(id=3, string=test, testEntityParent=TestEntityParent(id=1, stringTwo=testTwo, testEntities=null))]
and an error:
query did not return a unique result: 2;
Without dependencies everything works fine.
UPDATE:
Adding #Lock(LockModeType.PESSIMISTIC_WRITE) to the find method leads to
Feature not supported: "MVCC=TRUE && FOR UPDATE && JOIN"; SQL statement:
... same applies to
#Lock(LockModeType.PESSIMISTIC_WRITE)
#Query("SELECT e from TestEntity e join e.testEntityParent p where e.string = :string and p.stringTwo = :stringTwo ")
Optional<TestEntity> findWhatever(#Param("string") String string, #Param("stringTwo") String stringTwo);
... since for update is always generated.
Apparently, it was a stupid mistake I needed to replace orElse with orElseGet and a lambda and everything worked, even without all those #Lock, etc - tricks.
Still I don't understand what exactly went wrong with the transactions and why.

No composite key property found for type error in Spring JPA2

I have an error in spring JPA
org.springframework.data.mapping.PropertyReferenceException: No property CompanyId found for type CompanyUserDetail!
#Embeddable
public class CompanyUserKey implements Serializable {
public CompanyUserKey() {
}
#Column(name = "company_id")
private UUID companyId;
#Column(name = "user_name")
private String userName;
public UUID getCompanyId() {
return companyId;
}
public void setCompanyId(UUID companyId) {
this.companyId = companyId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
#Entity
#Table(name = "company_user_detail")
public class CompanyUserDetail {
#EmbeddedId
CompanyUserKey companyUserkey;
public CompanyUserKey getCompanyUserkey() {
return companyUserkey;
}
public void setCompanyUserkey(CompanyUserKey companyUserkey) {
this.companyUserkey = companyUserkey;
}
}
I am trying to access below method Service layer
#Component
public interface CompanyUserRepository extends JpaRepository<CompanyUserDetail, CompanyUserKey> {
public List<CompanyUserDetail> findByCompanyId(UUID companyId);
}
How can I achieve this ?
Thanks
Since in java model your CompanyUserKey is a property in the CompanyUserDetail class, I believe you should use full path (companyUserkey.companyId) to reach companyId:
public List<CompanyUserDetail> findByCompanyUserkeyCompanyId(UUID companyId);
Also note that you have a naming inconsistency: field in CompanyUserDetail is named companyUserkey instead of companyUserKey.
Assuming you are not using spring-data-jpa's auto generated implementations, your method contents might look something like the following:
FROM CompanyUserDetail c WHERE c.companyUserKey.companyId = :companyId
Now simply provide that query to the EntityManager
entityManager.createQuery( queryString, CompanyUserDetail.class )
.setParameter( "companyId", companyId )
.getResultList();
The key points are:
Query uses a named bind parameter called :companyId (not the leading :).
Parameter values are bound in a secondary step using setParameter method variants.
createQuery uses a second argument to influence type safety so that the return value from getResultList is a List<CompanyUserDetail> just like you requested.
Looking at spring-data-jpa's implementation however, I suspect it could look like this:
public interface CustomerUserRepository
extends JpaRepository<CompanyUserDetail, CompanyUserKey> {
#Query("select c FROM CompanyUserDetail c WHERE c.companyUserKey.companyId = :companyId")
List<CompanyUserDetail> findByCompanyId(#Param("companyId") UUID companyId);
}

How to write a search class to accept any type of parameter?

I'm using spring mvc and I created the CRUD functionality. But I want to create a search function that will allow me to find a user by any parameter (variable) as 'userid' or 'username' or 'lastname' or 'social security number' or whatever.
My userid is an integer type.
How can I do that? What is the SQL query for that?
How can I check if the input is integer or string and then go through the database by the given parameter and search for the user?
If you are using Hibernate for data access you can easily create universal finder using criteria API:
Abstract DAO class:
public abstract class AbstractHibernateDAO<T> {
private static final String PARAM_VALUE_PARAMETER = "paramValue";
private final Class<T> clazz;
#Autowired
private SessionFactory sessionFactory;
public AbstractHibernateDAO(Class<T> clazz) {
this.clazz = clazz;
}
public T findOne(String paramName, Object paramValue) {
Session session = sessionFactory.getCurrentSession();
#SuppressWarnings("unchecked")
T fetchedObject = (T) session.createCriteria(clazz).add(Restrictions.eq(paramName, paramValue)).uniqueResult();
return fetchedObject;
}
// Other CRUD methods.
}
Concrete DAO class for entity:
#Repository
#Transactional
public class ProductHibernateDAO extends AbstractHibernateDAO<Product> {
public ProductHibernateDAO() {
super(Product.class);
}
}
Or if you prefer to use HQL instead of Criteria API you can rewrite search method as:
public T findOne(String paramName, Object paramValue) {
Session session = sessionFactory.getCurrentSession();
StringBuilder queryText = new StringBuilder();
queryText.append("from ");
queryText.append(clazz.getSimpleName());
queryText.append(" where ");
queryText.append(paramName);
queryText.append("=:");
queryText.append(PARAM_VALUE_PARAMETER);
#SuppressWarnings("unchecked")
T fetchedObject = (T) session.createQuery(queryText.toString()).setParameter(PARAM_VALUE_PARAMETER, paramValue).uniqueResult();
return fetchedObject;
}
In this article you can find very good description how to create generic DAO with hibernate (Or if you prefer JPA there are also described how to do this with JPA).
Or if you prefer to use JDBC for data access I recommend you to look at Spring's JdbcTemplate. It simplifies development a lot. Here how you can implement universal finder using JdbcTemplate:
#Repository
#Transactional
public class ProductJDBCDAO implements DAO<Product> {
private static final String TABLE_NAME = "product";
#Autowired
private JdbcTemplate jdbcTemplate;
public Product findOne(String paramName, Object paramValue) {
RowMapper<Product> rowMapper = new RowMapper<Product>(){
public Product mapRow(ResultSet rs, int rowNum) throws SQLException {
long productId = rs.getLong("product_id");
// Other properties
Product product = new Product(...);
return product;
}
};
StringBuilder queryText = new StringBuilder();
queryText.append("select * from ");
queryText.append(TABLE_NAME);
queryText.append(" where ");
queryText.append(paramName);
queryText.append("=?");
Product fetchedObject = jdbcTemplate.queryForObject(queryText.toString(), rowMapper, paramValue);
return fetchedObject;
}
// Other CRUD methods
}
Ass you can see in all examples you don't need explicitly specify parameter type, you just add it as Object parameter.
If you will work with direct JDBC in such case I recommend you to use PreparedStatement and it's setObject(..) method. Query text will be similar to shown in the example with JdbcTemplate.

Resources