Just so I don't forget
Java 8 SE
Eclipse 2019-12
Spring Boot 2.2.4.RELEASE
I am trying to learn Spring Boot, and I am struggling to understand why a lambda doesn't compile. Here is the spring boot example (which compiles).
jdbcTemplate.query(
"SELECT id, first_name, last_name FROM customers WHERE first_name = ?", new Object[] { "Josh" },
(rs, rowNum) -> new Customer(rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name"))
).forEach(customer -> log.info(customer.toString()));
And here is my attempt to modify this example to my own needs:
#RestController
public class SwitchController {
#Autowired
JdbcTemplate jdbcTemplate;
#GetMapping
public Rows getSwitchRows() {
Rows switches = new Rows();
jdbcTemplate.query(
"SELECT swityp, oldkey, newkey, delete FROM table",
(rs, rowNum) -> new Switch(rs.getString("swityp"), rs.getString("oldkey"), rs.getString("newKey"), rs.getString("delete"))
).forEach(switch -> switches.addRow(switch));
return switches;
}
}
The lambda in the forEach() gives an error on -> which says Syntax error on token "->", ( expected and also on switches.addRow(switch) which says Syntax error on token "switch", delete this token. It is almost as if the forEach() doesn't recognize that I typed a lambda. Maybe what I thought was a lambda, isn't. If that is the case, what makes it not a lambda?
Here are my Switch and Rows classses in case that helps:
Switch.java
public class Switch {
private final String switchType;
private final String oldKey;
private final String newKey;
private final String delete;
public Switch(String switchType, String oldKey, String newKey, String delete) {
this.switchType = switchType;
this.oldKey = oldKey;
this.newKey = newKey;
this.delete = delete;
}
public String getSwitchType() {
return switchType;
}
public String getOldKey() {
return oldKey;
}
public String getNewKey() {
return newKey;
}
public String getDelete() {
return delete;
}
}
Rows.java
public class Rows {
private Object[] rows;
public Rows () {
super();
}
public void addRow (Object row) {
rows[rows.length] = row;
}
}
Related
currently I am trying to upgrade from hibernate 4 to hibernate5. But I am facing the issue of
org.hibernate.QueryException: Legacy-style query parameters (`?`) are no longer supported; use JPA-style ordinal parameters (e.g., `?1`)
But I can't seem to find the '?' within my query.
Below are the codes for it
public List<CustConfigDTO> getCustConfigDetails() throws DAOException
{
try
{
String sectionQuery = "select * from cust_config";
Query<?> query = getSession().createNativeQuery(sectionQuery, CustConfigDTO.class);
return (List<CustConfigDTO>) query.list();
}
catch( Exception ex )
{
LOGGER.error( ex );
throw new DAOException();
}
}
CustConfigDTO
public class CustConfigDTO implements java.io.Serializable
{
private String config_for;
private String config_value;
private String config_description;
public CustConfigDTO( String config_for,
String config_value,
)
{
this.config_for = config_for;
this.config_value = config_value;
}
public String getConfig_for()
{
return this.config_for;
}
public void setConfig_for( String config_for )
{
this.config_for = config_for;
}
public String getConfig_value()
{
return this.config_value;
}
public void setConfig_value( String config_value )
{
this.config_value = config_value;
}
May I know what is required to change from my code?
Thank you
Basically what I want to do is following code(I will get system param and will check if it is not null then if the current system on the code is not equal to that then set the dbName as parameter)
if (Objects.nonNull(query.getSystem())) {
if (!query.getSystem().equals(dbContextHolder.getCurrentDb().toString())) {
dbContextHolder.setCurrentDb(Enum.valueOf(DbTypeEnum.class, query.getSystem()));
}
}
I also want if the currentDb system is null then return null. What I try to do is something like
var res = Optional.ofNullable(dbContextHolder.getCurrentDb().toString())
.map(String::toString)
.filter(s -> !s.equals(dbType))
.orElse(Optional.ofNullable(dbType).orElse(null));
But as you see it is wrong and not working. How can I achieve that if parameter dbType is not equal to getCurrentDb then call the method setDbType(paramDbType) if they are equal then return one of them if currentDb is null then return null.
By reducing your problem down I just realized that you always want the value of query.getSystem() to be the context, therefore:
I reduced your code like this:
MockDbTypeEnum newMethod(MockQuery query, MockDbContextHolder dbContextHolder) {
return Optional
.ofNullable(query.getSystem())
.map(MockDbTypeEnum::valueOf)
.orElse(null);
}
MockDbTypeEnum oldMethod(MockQuery query, MockDbContextHolder dbContextHolder) {
if (Objects.nonNull(query.getSystem())) {
if (!query.getSystem().equals(dbContextHolder.getCurrentDb().toString())) {
dbContextHolder.setCurrentDb(Enum.valueOf(MockDbTypeEnum.class, query.getSystem()));
}
return dbContextHolder.getCurrentDb();
}
return null;
}
Also here are the mocks and tests I used to prove these methods are functionally the same for your purposes:
#ParameterizedTest
#CsvSource(value = {
"PSQL, PSQL, PSQL",
"PSQL, SQL, PSQL",
"SQL, SQL, SQL",
"SQL, PSQL, SQL",
"null, SQL, null",
"null, PSQL, null"
}, nullValues = {"null"})
void test(String system, MockDbTypeEnum currentDb, MockDbTypeEnum expectedResult) {
MockQuery query = new MockQuery(system);
MockDbContextHolder dbContextHolder = new MockDbContextHolder(currentDb);
MockDbTypeEnum result = oldMethod(query, dbContextHolder);
assertEquals(expectedResult, result);
MockDbTypeEnum newResult = newMethod(query, dbContextHolder);
assertEquals(expectedResult, newResult);
}
enum MockDbTypeEnum {
PSQL,
SQL
}
static class MockQuery {
private final String system;
public MockQuery(String system) {
this.system = system;
}
public String getSystem() {
return system;
}
}
static class MockDbContextHolder {
private MockDbTypeEnum currentDb;
public MockDbContextHolder(MockDbTypeEnum currentDb) {
this.currentDb = currentDb;
}
public MockDbTypeEnum getCurrentDb() {
return currentDb;
}
public void setCurrentDb(MockDbTypeEnum currentDb) {
this.currentDb = currentDb;
}
}
Here is the result:
Hi i'm trying to make a search using 4 fields but some of them might be null when I make the search. That's why I opted for queryDsl .
This is my pom.xml
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
I made ClientPredicate.java
final class ClientPredicates {
private ClientPredicates() {
}
static Predicate firstnameOrLastnameOrCinOrPhoneNberContainsIgnoreCase(String searchTerm) {
if (searchTerm == null || searchTerm.isEmpty()) {
return (Predicate) QClient.client.isNotNull();
} else {
return (Predicate) QClient.client.firstname.containsIgnoreCase(searchTerm)
.or(QClient.client.lastname.containsIgnoreCase(searchTerm)).or
(QClient.client.cin.containsIgnoreCase(searchTerm)).or(QClient.client.phoneNber.containsIgnoreCase(searchTerm));
}
}
}
QClient.java
#Generated("com.mysema.query.codegen.EntitySerializer")
public class QClient extends EntityPathBase<Client> {
private static final long serialVersionUID = -797939782L;
public static final QClient client = new QClient("client");
public final StringPath createdByUser = createString("createdByUser");
public final DateTimePath<java.time.ZonedDateTime> creationTime = createDateTime("creationTime", java.time.ZonedDateTime.class);
public final StringPath firstname = createString("firstname");
public final StringPath lastname = createString("lastname");
public final StringPath cin = createString("cin");
public final StringPath phoneNber = createString("phoneNber");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final DateTimePath<java.time.ZonedDateTime> modificationTime = createDateTime("modificationTime", java.time.ZonedDateTime.class);
public final StringPath modifiedByUser = createString("modifiedByUser");
public final NumberPath<Long> version = createNumber("version", Long.class);
public QClient(String variable) {
super(Client.class, forVariable(variable));
}
public QClient(Path<Client> path) {
super(path.getType(), path.getMetadata());
}
public QClient(PathMetadata<?> metadata) {
super(Client.class, metadata);
}
}
And in my controller I have this code:
#RequestMapping(value = "/seekClient", method = RequestMethod.POST, headers = "Accept=application/json")
public #ResponseBody List<Client> seekClient(#RequestBody Client client) {
Predicate firstnameAndLastnameAndCinAndPhoneNberAre = QClient.client.firstname.eq(client.getFirstname())
.and(QClient.client.lastname.eq(client.getLastname()));
System.out.println("*************************** "+firstnameAndLastnameAndCinAndPhoneNberAre);
List<Client> list = (List<Client>) clientRepository.findAll(firstnameAndLastnameAndCinAndPhoneNberAre);
return list;
}
The problem is every time I send a empty field I'm getting a nullPointerException.
Any help please. It's been hours that i'm blocked
I expect "send an empty field" means that in your controller the parameter is null. Therefore accessing it's methods will throw an exception. Add a null check in the controller and you should be good.
I have the following code:
PersonDao.java
#Repository
#Transactional
public class PersonDao implements PersonDaoIface {
Object property;
String order;
#Autowired
private SessionFactory sessionFactory;
public PersonDao() {
}
public PersonDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#SuppressWarnings("unchecked")
#Override
public List<Person> getAll(long first, long count) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Person.class);
this.setPaging(criteria, first, count);
addSort(criteria);
return criteria.list();
}
#Override
public long getAllCount() {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Person.class)
.setProjection(Projections.rowCount());
Long i = (Long) criteria.uniqueResult();
return i;
}
#Override
public List<Person> getByFilter(Person person, int first, int count) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Person.class);
criteria.add(Restrictions.eq("firstName", person.getFirstName()));
criteria.add(Restrictions.eq("lastName", person.getLastName()));
this.setPaging(criteria, first, count);
return criteria.list();
}
#Override
public long getByFilterCount(Person person) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Person.class);
criteria.add(Restrictions.eq("firstName", person.getFirstName()));
criteria.add(Restrictions.eq("lastName", person.getLastName()));
criteria.setProjection(Projections.rowCount());
Long result = (Long) criteria.uniqueResult();
return result;
}
private void setPaging(Criteria criteria, long first, long count) {
criteria.setFirstResult((int) first);
criteria.setMaxResults((int) count);
}
private void addSort(Criteria criteria) {
if (property != null) {
if (order.equalsIgnoreCase(SortOrder.ASCENDING.toString())) {
criteria.addOrder(Order.asc((String)property));
} else {
criteria.addOrder(Order.desc((String)property));
}
}
}
#Override
public void setSort(Object property, String order) {
this.property = property;
this.order = order;
}
}
SortableDataProvider
public class PersonSortableDataProvider extends SortableDataProvider {
private transient PersonDaoIface personDao;
public PersonSortableDataProvider(PersonDaoIface personDao) {
this.personDao = personDao;
}
public PersonSortableDataProvider() {
}
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public Iterator<Person> iterator(long first, long count) {
System.out.println(getSort());
return personDao.getAll(first, count).iterator();
}
#Override
public long size() {
long result = personDao.getAllCount();
return result;
}
#Override
public IModel<Person> model(final Object object) {
return new AbstractReadOnlyModel<Person>() {
#Override
public Person getObject() {
return (Person) object;
}
};
}
}
A panel with a data table using the sortable data provider
public DataDisplayPanel(String id) {
super(id);
List<IColumn> columns = new ArrayList<IColumn>();
columns.add(new PropertyColumn(new Model<String>("First Name"), "firstName"));
columns.add(new PropertyColumn(new Model<String>("Last Name"), "lastName"));
AjaxFallbackDefaultDataTable table = new AjaxFallbackDefaultDataTable("personData", columns,
personSortableDataProvider, 8);
table.addTopToolbar(new HeadersToolbar(table, personSortableDataProvider));
add(table);
}
I have paging done no problem but I am having trouble understanding how to get sorting working with hibernate, I can see how you could do the sorting from the java side of things but given that I could potentially get large data sets back I don't like this idea.
Given my code above does anyone have a way of getting the data table, on click of either first name or last name to then make the same query found in the iterator with the additional order by clause.
You are almost there. You just need an:
addOrder(Order.asc(columnName))
The doc is here.
To anyone that encounters this situation I have the following setup:
hibernate 4, spring 4 and wicket 6
I inject using Spring and it seems wicket and spring get confused if you inject within the SortableDataProvider.
I don't know what exactly happens; when i step over the project I will have a better idea but it appears setSort is not getting set correctly, when i move the Dao class out of sortable data provider and into the page and inject it there, then pass the dao instance into sortable data provider the sorting works correctly.
I am trying to create a "select from insert" within my Spring JdbcDaoSupport class and am having trouble figuring out how to get the data from the select statement and return it.
My EventJdbcTemplate (my DaoImpl):
#Service
public class EventJdbcTemplate extends JdbcDaoSupport implements EventDao {
private static final Logger LOGGER = Logger.getLogger(EventJdbcTemplate.class);
private static final String SQL_INSERT_EVENT = "SELECT EVENT_ID FROM FINAL TABLE " +
"(INSERT INTO EBT10DBB.SB0401T0 (EVENT_NAME, HOST_NAME, USER_ID) " +
"VALUES(?, ?, \'EMP0321\'))";
#Autowired
public EventJdbcTemplate(DataSource pDataSource) {
super.setDataSource(pDataSource);
}
#Override
public Integer createEvent(EventBean pEventBean) { //(Integer id, String eventName)
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Entering create(Event event) of EventJDBCTemplate.");
}
// This SQL works, but is for an INSERT only.
/*this.getJdbcTemplate().query(SQL_INSERT_EVENT, new Object[]{
pEventBean.getEventName(),
pEventBean.getHostName()
});*/
final List eventList = this.getJdbcTemplate().query(SQL_INSERT_EVENT, new Object[]{
pEventBean.getEventName(),
pEventBean.getHostName()
}, new EventRowMapper()
);
Event event = null;
for (int i = 0; i < eventList.size(); i++) {
event = (Event)eventList.get(i);
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Exiting create(Event event) of EventJDBCTemplate.");
}
//return statement -- should return either the entire "pEventBean", or
//just the unique key, "EVENT_ID".
return event.getId();
}
EventRowMapper class (Not sure is I'll need this for the select or not):
public class EventRowMapper implements RowMapper<Event> {
#Override
public Event mapRow(ResultSet rs, int rowNum) throws SQLException {
final EventBuilder event = new EventImpl.EventBuilder();
event.setId(rs.getInt("EVENT_ID"));
event.setEventName("EVENT_NAME");
event.setHostName("HOST_NAME");
return event.build();
}
}
So my goal is to return an Integer value that would be the unique key (EVENT_ID) that is created from the INSERT SQL.
You can use SimpleJdbcInsert provided by Spring to get back generated keys, see following documentation provided by Spring section
13.5.2 Retrieving auto-generated keys using SimpleJdbcInsert
Here is the Link